Conversation
# Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
…n in OpenAPI paths
|
I have addressed the second round of review comments. Key changes:
Verified with |
| let lastUpdated = '' | ||
| try { | ||
| // Use git log to get the last commit date | ||
| lastUpdated = execSync(`git log -1 --format=%cd --date=iso-strict "${filePath}"`).toString().trim() |
There was a problem hiding this comment.
The execSync call uses string interpolation to embed filePath directly into a shell command without sanitization. Although filePath is derived from fs.readdirSync, a malicious filename (e.g., "; rm -rf / #.md) in the static/ directory could lead to command injection. Use execFileSync instead of execSync to pass arguments safely, or validate that filenames contain only expected characters before running the command.
|
|
||
| * **Access:** Request a copy of the data we hold about you (Discord ID and linked Wallet), you can review this information in the service homepage (`/home`). | ||
| * **Rectification:** Update your data (typically done by re-syncing your Discord profile). | ||
| * **Erasure ("Right to be Forgotten"):** You may unlink your wallet and request deletion of your account. We support "soft-deletes" and unlinking capabilities. |
There was a problem hiding this comment.
The privacy policy states "We support 'soft-deletes' and unlinking capabilities" (line 56), but the actual implementation in delete_me performs hard deletion of wallets (DELETE FROM wallets WHERE user_id = ?) and anonymizes the user row rather than soft-deleting. Update this statement to accurately reflect the implementation, e.g., "You may delete your account, which will permanently remove your wallets and anonymize your user profile."
| * **Erasure ("Right to be Forgotten"):** You may unlink your wallet and request deletion of your account. We support "soft-deletes" and unlinking capabilities. | |
| * **Erasure ("Right to be Forgotten"):** You may delete your account, which will permanently remove your wallets and anonymize your user profile. You may also unlink your wallet without deleting your account. |
| setIsDeleteModalOpen(false); | ||
| } catch (err) { | ||
| console.error('Failed to delete account:', err); |
There was a problem hiding this comment.
If deleteAccount() throws an error (network failure, non-200 response, etc.), the modal is left open because setIsDeleteModalOpen(false) is only called on success. The error message is logged to console and set via setError, but the user is stuck in the modal with no clear recovery path. Consider calling setIsDeleteModalOpen(false) in a finally block, or adding UI feedback (e.g., displaying the error inside the modal) to improve the user experience.
| setIsDeleteModalOpen(false); | |
| } catch (err) { | |
| console.error('Failed to delete account:', err); | |
| } catch (err) { | |
| console.error('Failed to delete account:', err); | |
| alert('Failed to delete your profile. Please try again in a moment, or contact support if the problem persists.'); | |
| } finally { | |
| setIsDeleteModalOpen(false); |
| Your account has been permanently deleted at your request to fulfill your <a href="https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/individual-rights/individual-rights/right-to-erasure/" style={{ color: '#ef4444', textDecoration: 'underline', textUnderlineOffset: '4px', transition: 'opacity 0.2s' }} onMouseOver={(e) => e.currentTarget.style.opacity = '0.8'} onMouseOut={(e) => e.currentTarget.style.opacity = '1'}><strong>Right to be Forgotten / Right to erasure</strong></a> under GDPR. | ||
| </p> | ||
| <p> | ||
| As part of our commitment to your privacy, your Discord ID and associated Wallet Addresses have been completely delisted and barred from future use to ensure that this data cannot be re-processed or used to recreate a profile on this platform. |
There was a problem hiding this comment.
Inconsistent terminology: the deleted page uses "delisted" (line 49), but the rest of the codebase uses "denylisted" (e.g., identity_hashes table, error messages like "This wallet has been denylisted due to account deletion"). For consistency and clarity, consider updating "delisted" to "denylisted" or use a more user-friendly term like "blocked" that aligns with the inclusive language goals of this PR.
| As part of our commitment to your privacy, your Discord ID and associated Wallet Addresses have been completely delisted and barred from future use to ensure that this data cannot be re-processed or used to recreate a profile on this platform. | |
| As part of our commitment to your privacy, your Discord ID and associated Wallet Addresses have been permanently blocked from future use to ensure that this data cannot be re-processed or used to recreate a profile on this platform. |
| let identity_hash_pepper = std::env::var("IDENTITY_HASH_PEPPER") | ||
| .expect("IDENTITY_HASH_PEPPER must be set for security and deterministic hashing"); |
There was a problem hiding this comment.
The new required environment variable IDENTITY_HASH_PEPPER is not documented in .env.example. Since state.rs uses .expect() to require this variable at startup, developers will experience cryptic errors if they don't set it. Add an entry to .env.example with a comment explaining its purpose (e.g., "Secret pepper for hashing denylisted identifiers. Generate a strong random string.") to guide developers and ensure smooth setup.
1. Title
feat: implement user profile deletion and compliance updates
2. Description
What?
This PR introduces the ability for users to delete their profiles, adds essential legal documentation (Privacy Policy, Terms of Service, etc.), and updates the codebase to use more inclusive language ("denylist" instead of "blacklist").
Why?
How?
delete_profileendpoint inauth.rs.denylistedterminology.ConfirmationModalfor critical actions like account deletion.deleted.tsxroute for the post-deletion state.$page.tsxroute to render them.DashboardLayoutandAuthProviderto handle the new routes and states.3. Type of Change
feat: A new featurefix: A bug fixdocs: Documentation only changesstyle: Changes that do not affect the meaning of the code (white-space, formatting, etc.)refactor: A code change that neither fixes a bug nor adds a featureperf: A code change that improves performancetest: Adding missing tests or correcting existing testschore: Changes to the build process or auxiliary tools and libraries4. Development Checklist
cargo fmtandcargo clippy.bun run lintin thefrontenddirectory.sqlx migrate runand updatedsqlx-data.jsonviacargo sqlx prepare.5. Security Assessment
Evaluating against OWASP Top 10:2025 guidelines.
AuthenticatedUserextractors properly validate session state and that deletion is restricted to the owner.6. Frontend (if applicable)
7. Reviewer Feedback & Resolution
This PR follows the "Fix & Reply" loop for all unresolved comments.