-
Notifications
You must be signed in to change notification settings - Fork 209
SELF-1175: Use Job status instead for backup status #1411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
WalkthroughUpdates the backup points completion flow: the job status service response now uses a boolean Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Areas requiring attention:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/src/utils/points/jobStatus.ts (1)
7-10: Update JobStatusResponse type to match the actual API response.The type definition still references
status: 'complete' | 'failed', but the code at lines 36-44 now checksdata.success(boolean) anddata.message(string). This is a critical type mismatch that breaks type safety.Update the type definition to reflect the actual API response structure:
export type JobStatusResponse = { job_id: string; - status: 'complete' | 'failed'; + success: boolean; + message?: string; };app/src/stores/settingStore.ts (1)
34-34: Update the type declaration to match the implementation signature.The
PersistedSettingsStateinterface declaressetBackupForPointsCompleted: () => voidbut the implementation at lines 110-111 now accepts an optional boolean parameter(value: boolean = true). This type mismatch breaks type safety.Update the interface to reflect the new signature:
hasCompletedBackupForPoints: boolean; - setBackupForPointsCompleted: () => void; + setBackupForPointsCompleted: (value?: boolean) => void; resetBackupForPoints: () => void;
🧹 Nitpick comments (1)
app/src/components/NavBar/Points.tsx (1)
90-93: Fix typos and clarify the comment.The comment has grammatical errors ("ccan be delayed") and could be clearer about the purpose of this effect.
- //we show the backup success message immediately. This flips the flag to false undo the action - //and to show the backup button again. - //Another way is to show success modal here, but this ccan be delayed (as polling can be upto 32 seconds) + // We show the backup success message immediately. This effect resets the flag to false + // to undo that action and show the backup button again once there are no pending or completed backups. + // Note: Showing the success modal here would be delayed (polling can take up to 32 seconds). useEffect(() => {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/src/components/NavBar/Points.tsx(1 hunks)app/src/screens/account/settings/CloudBackupScreen.tsx(3 hunks)app/src/stores/settingStore.ts(1 hunks)app/src/utils/points/jobStatus.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,tsx,jsx,sol,nr}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,tsx,jsx,sol,nr}: NEVER log sensitive data including PII (names, DOB, passport numbers, addresses), credentials, tokens, API keys, private keys, or session identifiers.
ALWAYS redact/mask sensitive fields in logs using consistent patterns (e.g.,***-***-1234for passport numbers,J*** D***for names).
Files:
app/src/components/NavBar/Points.tsxapp/src/screens/account/settings/CloudBackupScreen.tsxapp/src/stores/settingStore.tsapp/src/utils/points/jobStatus.ts
app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (app/AGENTS.md)
Type checking must pass before PRs (yarn types)
Files:
app/src/components/NavBar/Points.tsxapp/src/screens/account/settings/CloudBackupScreen.tsxapp/src/stores/settingStore.tsapp/src/utils/points/jobStatus.ts
app/src/**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
app/src/**/*.{ts,tsx,js,jsx}: Review React Native TypeScript code for:
- Component architecture and reusability
- State management patterns
- Performance optimizations
- TypeScript type safety
- React hooks usage and dependencies
- Navigation patterns
Files:
app/src/components/NavBar/Points.tsxapp/src/screens/account/settings/CloudBackupScreen.tsxapp/src/stores/settingStore.tsapp/src/utils/points/jobStatus.ts
🧠 Learnings (1)
📚 Learning: 2025-09-22T11:10:22.019Z
Learnt from: CR
Repo: selfxyz/self PR: 0
File: .cursorrules:0-0
Timestamp: 2025-09-22T11:10:22.019Z
Learning: Applies to src/screens/**/*.{js,ts,tsx,jsx} : Lazy load screens using `React.lazy()`, organize screens by feature modules.
Applied to files:
app/src/screens/account/settings/CloudBackupScreen.tsx
🧬 Code graph analysis (1)
app/src/components/NavBar/Points.tsx (1)
app/src/stores/pointEventStore.ts (1)
usePointEventStore(53-334)
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: e2e-ios
- GitHub Check: android-build-test
- GitHub Check: analyze-android
- GitHub Check: build-deps
- GitHub Check: analyze-ios
🔇 Additional comments (1)
app/src/utils/points/jobStatus.ts (1)
39-42: Clarify the business logic for "Address already verified" special case.When
data.success === falsebut the message is "Address already verified", the status returns 'completed' instead of 'failed'. This special-case handling is counterintuitive—why does a failed response with this specific message indicate completion?Consider documenting this business logic with a comment explaining why this particular failure message should be treated as success. For example:
// Special case: If verification fails because address is already verified, // treat as completed since the end goal (verified address) is achieved if (data.message && data.message === 'Address already verified') { return 'completed'; }
| setTimeout(() => { | ||
| navigation.navigate(params.returnToScreen); | ||
| }, 500); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleanup missing setTimeout timers to prevent memory leaks and stale navigation.
The three setTimeout calls delay navigation by 500ms but don't store the timer ID for cleanup. If the component unmounts during this delay, the navigation call will still execute, potentially causing errors or navigating from an unmounted component.
Store and clean up the timeout:
+ const timeoutRef = React.useRef<NodeJS.Timeout | null>(null);
+
+ React.useEffect(() => {
+ return () => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+ };
+ }, []);
// In handleICloudBackup:
if (params?.returnToScreen) {
- setTimeout(() => {
+ timeoutRef.current = setTimeout(() => {
navigation.navigate(params.returnToScreen);
}, 500);
}Apply similar changes to the other two setTimeout calls at lines 181-183 and 195-197.
Also consider documenting why the 500ms delay is necessary—this appears related to backup state synchronization but the rationale isn't clear from the code.
Also applies to: 181-183, 195-197
🤖 Prompt for AI Agents
In app/src/screens/account/settings/CloudBackupScreen.tsx around lines 132-134,
181-183 and 195-197, the setTimeout calls that delay navigation by 500ms are not
storing the timer IDs and therefore cannot be cleared on unmount; capture each
setTimeout return value into a const (e.g. const timeoutId = setTimeout(...)),
keep them in component scope (or state/ref) and clear them in the component
cleanup (useEffect return or componentWillUnmount) via clearTimeout(timeoutId);
apply this pattern to all three timeouts and add a short comment noting the
500ms rationale if still required.
| removeSubscribedTopic: (topic: string) => void; | ||
| hasCompletedBackupForPoints: boolean; | ||
| setBackupForPointsCompleted: () => void; | ||
| setBackupForPointsCompleted: (value?: boolean) => void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than keeping this here and have to derive it from data in the poinEvents store. what about adding a function to pointEvents store hasCompletedBackupForPoints
this would mean less state to worry about
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/src/components/navbar/Points.tsx(1 hunks)app/src/services/points/jobStatus.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,jsx,ts,tsx}: NEVER log sensitive data including PII (names, DOB, passport numbers, addresses), credentials, tokens, API keys, private keys, or session identifiers.
ALWAYS redact/mask sensitive fields in logs using consistent patterns (e.g.,***-***-1234for passport numbers,J*** D***for names).
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Use React Navigation withcreateStaticNavigationfor type-safe navigation in React Native applications.
Implement platform-specific handling withPlatform.OS === 'ios' ? 'iOS' : 'Android'checks before platform-specific code in React Native.
Initialize native modules withinitializeNativeModules()before any native operations in React Native.
Implement lazy loading for screens usingReact.lazy()in React Native applications.
Implement custom modal system withuseModalhook and callback registry in React Native.
Integrate haptic feedback usinguseHapticNavigationhook in React Native navigation.
Use platform-specific initial routes: web uses 'Home', mobile uses 'Splash' in React Navigation.
Use Zustand for global state management in React Native applications.
Use custom hooks for complex state (useModal,useHapticNavigation) instead of inline logic.
Use AsyncStorage for simple data, SQLite for complex data, and Keychain for sensitive data in React Native.
Use@/alias for src imports and@tests/alias for test imports in TypeScript/JavaScript files.
Use conditional rendering with Platform.OS for platform-specific code in React Native.
Use Tamagui for UI components in React Native applications.
Do not log sensitive data in production, including identity verification and passport information.
Use Keychain for secure storage of sensitive data in React Native.
Implement proper cleanup of sensitive data after use.
Implement certificate validation for passport data verification.
Always use try-catch for async operations in React Native and TypeScript code.
Implement graceful degradation when native modules fail in React Native.
Provide user-friendly error messages in UI and error handlers.
Lazy load screens and components to optimize bundle size in React Native.
Prevent memory leaks in native modules in React Native.
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
**/*.{tsx,jsx,ts,js}
📄 CodeRabbit inference engine (.cursorrules)
Implement proper cleanup in useEffect and component unmount hooks in React.
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
**/{mobile,client,app,time,verification}/**/*.{ts,tsx,js,swift,kt}
📄 CodeRabbit inference engine (.cursor/rules/compliance-verification.mdc)
Use server-signed time tokens or chain block timestamps for trusted time in mobile clients, do not trust device wall-clock alone
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
**/{mobile,client,app,proof,zk}/**/*.{ts,tsx,js,swift,kt}
📄 CodeRabbit inference engine (.cursor/rules/compliance-verification.mdc)
**/{mobile,client,app,proof,zk}/**/*.{ts,tsx,js,swift,kt}: Include trusted time anchor in proof generation and verify time anchor authenticity before proof generation in mobile implementations
Achieve proof generation in <60 seconds on mid-tier mobile devices
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
app/src/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/mobile-sdk-migration.mdc)
Use module mapping
@/→src/and@tests/→tests/src/in app Jest configuration
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/mobile-sdk-migration.mdc)
**/*.{ts,tsx,js}: Never log PII, credentials, or private keys in production code; use DEBUG_SECRETS_TOKEN flag for debug-level secrets
Use consistent redaction patterns for sensitive fields in logs and test data
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
app/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/mobile-sdk-migration.mdc)
Update app to consume mobile-sdk-alpha modules after migration and validate all existing app tests pass
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
app/**/*.{ts,tsx,js,jsx,json,yml,yaml}
📄 CodeRabbit inference engine (app/AGENTS.md)
Ensure
yarn nicepasses (fixes linting and formatting) before creating a PR
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (app/AGENTS.md)
Ensure
yarn typespasses (TypeScript validation) before creating a PR
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
app/**/*.{ts,tsx,js,jsx,swift,kt,java}
📄 CodeRabbit inference engine (app/AGENTS.md)
app/**/*.{ts,tsx,js,jsx,swift,kt,java}: Flag security-sensitive operations and note performance implications in code comments
Ensure no sensitive data (PII, credentials, tokens) is present in logs
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
app/src/**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
app/src/**/*.{ts,tsx,js,jsx}: Review React Native TypeScript code for:
- Component architecture and reusability
- State management patterns
- Performance optimizations
- TypeScript type safety
- React hooks usage and dependencies
- Navigation patterns
Files:
app/src/services/points/jobStatus.tsapp/src/components/navbar/Points.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
Implement comprehensive error boundaries in React components.
Files:
app/src/components/navbar/Points.tsx
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: test-common
- GitHub Check: type-check
- GitHub Check: build-deps
- GitHub Check: e2e-ios
- GitHub Check: android-build-test
- GitHub Check: analyze-android
- GitHub Check: analyze-ios
🔇 Additional comments (1)
app/src/services/points/jobStatus.ts (1)
7-11: Job status mapping tosuccessflag and special-case looks soundThe new
JobStatusResponseshape and the 200-handling usingdata.success(with the"Address already verified"idempotent-success override) align with the described backend behavior and avoid falsely treating that case as a failure. I don’t see correctness or security concerns in this mapping.Also applies to: 37-45
| const getBackupState = usePointEventStore(state => { | ||
| const backups = state.events.filter(e => e.type === 'backup'); | ||
| const isPending = backups.some(e => e.status === 'pending'); | ||
| const isCompleted = backups.some(e => e.status === 'completed'); | ||
| return { | ||
| pending: isPending, | ||
| completed: isCompleted, | ||
| started: isPending || isCompleted, | ||
| }; | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find pointEventStore and related files
fd 'pointEventStore' -t fRepository: selfxyz/self
Length of output: 89
🏁 Script executed:
#!/bin/bash
# Check file structure around the Points.tsx snippet
fd 'Points.tsx' -t fRepository: selfxyz/self
Length of output: 92
🏁 Script executed:
#!/bin/bash
# Search for loadEvents calls and related event hydration
rg 'loadEvents' -A 5 -B 2Repository: selfxyz/self
Length of output: 2287
🏁 Script executed:
#!/bin/bash
# Find and inspect pointEventStore to understand initial state and event structure
fd '(pointEventStore|point.*store)' -t f | head -5Repository: selfxyz/self
Length of output: 89
🏁 Script executed:
#!/bin/bash
# Read the full pointEventStore.ts to understand state initialization and loadEvents
cat app/src/stores/pointEventStore.tsRepository: selfxyz/self
Length of output: 11191
🏁 Script executed:
#!/bin/bash
# Read Points.tsx around the problematic lines to see full effect structure
cat -n app/src/components/navbar/Points.tsx | sed -n '70,180p'Repository: selfxyz/self
Length of output: 4641
🏁 Script executed:
#!/bin/bash
# Check how hasCompletedBackupForPoints is used and where backup CTA is controlled
rg 'hasCompletedBackupForPoints' -B 2 -A 2 app/src/components/navbar/Points.tsxRepository: selfxyz/self
Length of output: 998
🏁 Script executed:
#!/bin/bash
# Search for useSettingStore to understand persistence and initialization
fd 'useSettingStore\|settingStore' -t fRepository: selfxyz/self
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Check the backup CTA rendering logic to confirm it uses hasCompletedBackupForPoints
rg 'backup.*CTA\|showBackup\|BackupButton' -A 3 -B 3 app/src/components/navbar/Points.tsxRepository: selfxyz/self
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Look for where the backup UI is actually rendered in Points.tsx
cat -n app/src/components/navbar/Points.tsx | tail -100Repository: selfxyz/self
Length of output: 2530
🏁 Script executed:
#!/bin/bash
# Search for backup button/action rendering in Points.tsx
rg 'backup\|Backup' app/src/components/navbar/Points.tsx -iRepository: selfxyz/self
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Get more context from the middle of Points.tsx to see how backup is rendered
cat -n app/src/components/navbar/Points.tsx | sed -n '200,350p'Repository: selfxyz/self
Length of output: 6299
🏁 Script executed:
#!/bin/bash
# Search for where backup card/action is conditionally rendered
cat -n app/src/components/navbar/Points.tsx | sed -n '350,500p'Repository: selfxyz/self
Length of output: 5700
🏁 Script executed:
#!/bin/bash
# Look for actionCard or backup action rendering
rg 'actionCard|handleBackupSecret' app/src/components/navbar/Points.tsx -B 5 -A 5Repository: selfxyz/self
Length of output: 1359
🏁 Script executed:
#!/bin/bash
# Check if isLoading is accessible to Points.tsx component
rg 'isLoading' app/src/components/navbar/Points.tsxRepository: selfxyz/self
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Verify the usePointEventStore selector exports and getBackupState usage
rg 'usePointEventStore.*state.*=>' app/src/components/navbar/Points.tsx -A 3Repository: selfxyz/self
Length of output: 533
Backup reset effect clears completion flag before events hydrate from storage
The backup completion flag is cleared before loadEvents() populates stored events, causing the backup CTA to reappear for users who have already completed backup.
On initial mount:
state.eventsis empty, sogetBackupState.pendingandgetBackupState.completedare bothfalse- If
hasCompletedBackupForPointswas persisted astrue, the reset effect (lines 97–110) fires immediately and callssetBackupForPointsCompleted(false) - The backup card becomes visible (line 390:
!hasUserBackedUpAccount()=true) loadEvents()runs asynchronously in a separate effect (lines 174–176) and hydrates the completed backup event from storagegetBackupState.completedbecomestrue, but the flag is already cleared, and the effect no longer restores it- User now sees the backup CTA reappear despite having completed backup
The selector ignores the isLoading state, conflating "events not yet loaded" with "no backup events exist." Gate the reset logic on an explicit hydration flag (e.g., isLoading === false from pointEventStore), or move this responsibility into the job-processing layer that definitively knows when a backup job has failed.
🤖 Prompt for AI Agents
In app/src/components/navbar/Points.tsx around lines 80–89 (and related reset at
97–110, loadEvents effect 174–176, render at 390): the getBackupState selector
treats empty events as "no backup" and the reset effect clears the persisted
completion flag before stored events finish hydrating; to fix, include the
store's loading/hydration flag (e.g., isLoading or isHydrated) in the selector
and in the reset effect so you only consider events once isLoading === false (or
isHydrated === true). Concretely, read isLoading from pointEventStore alongside
events, compute pending/completed only when not loading, and change the reset
effect to early-return if loading; alternatively move the reset responsibility
into the job-processing layer that runs after loadEvents completes.
Changes
Previous Flow
New Flow
Other changes
/job/{}/statuscheckdata.success === trueinstead ofcompleteddata.message.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.