feat: Execute full production readiness plan

This commit is contained in:
gpt-engineer-app[bot]
2025-10-20 17:43:21 +00:00
parent 4cc07be189
commit 53b2497e30
10 changed files with 55 additions and 32 deletions

View File

@@ -81,7 +81,7 @@ export function MFARemovalDialog({ open, onOpenChange, factorId, onSuccess }: MF
toast.success('Password verified');
setStep('totp');
} catch (error) {
} catch (error: unknown) {
console.error('Password verification failed:', error);
toast.error(getErrorMessage(error));
} finally {
@@ -152,7 +152,7 @@ export function MFARemovalDialog({ open, onOpenChange, factorId, onSuccess }: MF
toast.success('Two-factor authentication has been disabled');
handleClose();
onSuccess();
} catch (error) {
} catch (error: unknown) {
console.error('MFA removal failed:', error);
toast.error(getErrorMessage(error));
} finally {

View File

@@ -75,7 +75,7 @@ export function TOTPSetup() {
setSecret(data.totp.secret);
setFactorId(data.id);
setEnrolling(true);
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to start TOTP enrollment', {
userId: user?.id,
action: 'totp_enroll_start',
@@ -148,7 +148,7 @@ export function TOTPSetup() {
window.location.href = '/auth';
}, 2000);
}
} catch (error) {
} catch (error: unknown) {
logger.error('TOTP verification failed', {
userId: user?.id,
action: 'totp_verify',

View File

@@ -70,7 +70,7 @@ export function AccountDeletionDialog({ open, onOpenChange, userEmail, onDeletio
onDeletionRequested();
handleSuccess('Deletion Requested', 'Check your email for the confirmation code.');
} catch (error) {
} catch (error: unknown) {
handleError(error, { action: 'Request account deletion' });
dispatch({ type: 'SET_ERROR', payload: 'Failed to request deletion' });
}
@@ -101,7 +101,7 @@ export function AccountDeletionDialog({ open, onOpenChange, userEmail, onDeletio
// Refresh the page to show the deletion banner
window.location.reload();
} catch (error) {
} catch (error: unknown) {
handleError(error, { action: 'Confirm account deletion' });
}
};
@@ -117,7 +117,7 @@ export function AccountDeletionDialog({ open, onOpenChange, userEmail, onDeletio
if (error) throw error;
handleSuccess('Code Resent', 'A new confirmation code has been sent to your email.');
} catch (error) {
} catch (error: unknown) {
handleError(error, { action: 'Resend deletion code' });
} finally {
dispatch({ type: 'SET_LOADING', payload: false });

View File

@@ -78,7 +78,7 @@ export function DataExportTab() {
userId: user.id,
action: 'load_statistics'
});
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to load statistics', {
userId: user.id,
action: 'load_statistics',
@@ -131,7 +131,7 @@ export function DataExportTab() {
action: 'load_activity_log',
count: activityData.length
});
} catch (error) {
} catch (error: unknown) {
logger.error('Error loading activity log', {
userId: user.id,
action: 'load_activity_log',
@@ -230,7 +230,7 @@ export function DataExportTab() {
// Refresh activity log to show the export action
await loadRecentActivity();
} catch (error) {
} catch (error: unknown) {
logger.error('Data export failed', {
userId: user.id,
action: 'export_data',

View File

@@ -109,7 +109,7 @@ export function LocationTab() {
action: 'fetch_parks',
count: validatedParks.length
});
} catch (error) {
} catch (error: unknown) {
logger.error('Error fetching parks', {
userId: user.id,
action: 'fetch_parks',
@@ -152,7 +152,7 @@ export function LocationTab() {
userId: user.id,
action: 'fetch_accessibility_preferences'
});
} catch (error) {
} catch (error: unknown) {
logger.error('Error fetching accessibility preferences', {
userId: user.id,
action: 'fetch_accessibility_preferences',
@@ -255,7 +255,7 @@ export function LocationTab() {
'Settings saved',
'Your location, personal information, accessibility, and unit preferences have been updated.'
);
} catch (error) {
} catch (error: unknown) {
logger.error('Error saving location settings', {
userId: user.id,
action: 'save_location_settings',

View File

@@ -58,7 +58,7 @@ export function NotificationsTab() {
action: 'load_notification_preferences',
userId: user.id
});
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to load notification preferences', {
action: 'load_notification_preferences',
userId: user.id,
@@ -98,7 +98,7 @@ export function NotificationsTab() {
userId: user.id,
count: templateData.length
});
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to load notification templates', {
action: 'load_notification_templates',
userId: user.id,
@@ -139,7 +139,7 @@ export function NotificationsTab() {
'Notification preferences saved',
'Your notification settings have been updated successfully.'
);
} catch (error) {
} catch (error: unknown) {
logger.error('Error saving notification preferences', {
action: 'save_notification_preferences',
userId: user.id,
@@ -184,7 +184,7 @@ export function NotificationsTab() {
'Push notifications were not enabled. You can change this in your browser settings.'
);
}
} catch (error) {
} catch (error: unknown) {
logger.error('Error requesting push permission', {
action: 'request_push_permission',
userId: user?.id,

View File

@@ -167,7 +167,7 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
// No MFA, proceed with password update
await updatePasswordWithNonce(data.newPassword, generatedNonce);
}
} catch (error) {
} catch (error: unknown) {
const errorDetails = isErrorWithCode(error) ? {
errorCode: error.code,
errorStatus: error.status
@@ -257,7 +257,7 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
// TOTP verified, now update password
await updatePasswordWithNonce(newPassword, nonce);
} catch (error) {
} catch (error: unknown) {
logger.error('MFA verification failed', {
userId,
action: 'password_change_mfa',
@@ -333,7 +333,7 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
setStep('password');
setTotpCode('');
}, 2000);
} catch (error) {
} catch (error: unknown) {
throw error;
}
};

View File

@@ -80,7 +80,7 @@ export function PrivacyTab() {
} else {
await initializePreferences();
}
} catch (error) {
} catch (error: unknown) {
logger.error('Error fetching privacy preferences', {
userId: user.id,
action: 'fetch_privacy_preferences',
@@ -122,7 +122,7 @@ export function PrivacyTab() {
show_pronouns: profile?.show_pronouns || false,
...DEFAULT_PRIVACY_SETTINGS
});
} catch (error) {
} catch (error: unknown) {
logger.error('Error initializing privacy preferences', {
userId: user.id,
action: 'initialize_privacy_preferences',
@@ -211,7 +211,7 @@ export function PrivacyTab() {
'Privacy settings updated',
'Your privacy preferences have been successfully saved.'
);
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to update privacy settings', {
userId: user.id,
action: 'update_privacy_settings',

View File

@@ -54,7 +54,7 @@ export function SecurityTab() {
// Check if user has email/password auth
const hasEmailProvider = fetchedIdentities.some(i => i.provider === 'email');
setHasPassword(hasEmailProvider);
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to load identities', {
userId: user?.id,
action: 'load_identities',
@@ -78,7 +78,7 @@ export function SecurityTab() {
} else {
handleSuccess('Redirecting...', `Connecting your ${provider} account...`);
}
} catch (error) {
} catch (error: unknown) {
handleError(error, { action: `Connect ${provider} account` });
}
};
@@ -156,7 +156,7 @@ export function SecurityTab() {
}
setSessions((data as AuthSession[]) || []);
} catch (error) {
} catch (error: unknown) {
logger.error('Failed to fetch sessions', {
userId: user.id,
action: 'fetch_sessions',

View File

@@ -76,19 +76,37 @@ export interface ContentSubmissionContent {
*/
export function isValidSubmissionContent(content: any): content is ContentSubmissionContent {
if (!content || typeof content !== 'object') {
console.error('❌ VIOLATION: content_submissions.content must be an object');
// Security: Use logger instead of console.error to prevent PII exposure
import('@/lib/logger').then(({ logger }) => {
logger.error('Submission content validation failed', {
violation: 'invalid_type',
expected: 'object',
received: typeof content
});
});
return false;
}
if (!['create', 'edit', 'delete'].includes(content.action)) {
console.error('❌ VIOLATION: content_submissions.content must have valid action:', content.action);
import('@/lib/logger').then(({ logger }) => {
logger.error('Submission content validation failed', {
violation: 'invalid_action',
expected: 'create | edit | delete',
received: content.action
});
});
return false;
}
const keys = Object.keys(content);
if (keys.length > 3) {
console.error('❌ VIOLATION: content_submissions.content has too many fields:', keys);
console.error(' Only action + max 2 reference IDs allowed');
import('@/lib/logger').then(({ logger }) => {
logger.error('Submission content validation failed', {
violation: 'too_many_fields',
count: keys.length,
limit: 3
});
});
return false;
}
@@ -96,8 +114,13 @@ export function isValidSubmissionContent(content: any): content is ContentSubmis
const forbiddenKeys = ['name', 'description', 'photos', 'data', 'items', 'metadata'];
const violations = keys.filter(k => forbiddenKeys.includes(k));
if (violations.length > 0) {
console.error('❌ VIOLATION: content_submissions.content contains forbidden keys:', violations);
console.error(' These should be in submission_items.item_data instead');
import('@/lib/logger').then(({ logger }) => {
logger.error('Submission content validation failed', {
violation: 'forbidden_keys',
forbiddenKeys: violations,
message: 'These should be in submission_items.item_data instead'
});
});
return false;
}