- Normalize emails to lowercase on user creation
- Use case-insensitive lookup in get_user_by_email
- Add merge_duplicate_email_users script to merge existing duplicates
- Add unit and integration tests to prevent regression
- Update CLAUDE.md with tmux-hosts production troubleshooting
Implements per-worker database isolation for parallel test runs:
- Add pytest-xdist and pytest-cov to test dependencies
- Configure Makefile to run tests with -n auto flag
- Update test.ini to use environment variable for database path
- Create conftest.py with per-worker database isolation
- Enable SQLite WAL mode for better concurrency
- Auto-cleanup test databases after completion
Expected performance improvement similar to make_post_sell (~16x speedup).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add google_site_verification column to rb_namespace table
- Add settings form field in Stand-alone Mode Settings
- Render meta tag on root path when set
- Update CLAUDE.md with Alembic migration workflow
- Fix development.ini alembic paths
Tests cover:
- Anonymous reply creates UserSurrogate
- Anonymous reply with no name defaults to 'Anonymous'
- Regular namespace still requires email
- Anonymous comments are marked as verified
- Namespace settings toggle for allow_anonymous
When enabled, commenters can post with just a display name (no email required).
Comments are attached to UserSurrogate instead of User.
Trade-offs for anonymous commenters:
- No email notifications for replies
- Cannot edit their comments
- Cannot log in to manage comments
- No cross-site identity
Works with existing moderation (hide_unless_approved) - anonymous
comments are never auto-approved when moderation is enabled.
- Replace multiple forms with single unified payment form
- Remove deprecated pay_what_you_can preferences (no longer needed with Stripe Checkout)
- Remove pay-what-you-can route and view
- Simplify setup-namespace to just link to billing
- Update tests for new billing UI
- Remove User.stripe_id column (no longer used with Stripe Checkout)
- Show billing link to all authenticated users in phone menu
- Remove old Stripe customer cleanup from tests
- Add test_stripe.py with unit tests for checkout module and Payment model
- Add functional tests for billing views (pay-what-you-can, checkout, success)
- Fix mock imports for Python 3 compatibility (unittest.mock)
- Remove unused stripe.j2 imports from templates
- Remove jQuery (84KB) - all functionality now vanilla JS
- Remove legacy google-analytics.j2 (using gtag v4 instead)
- Remove ie8.polyfils.min.js (IE8 is dead)
- Add X-Requested-With header for AJAX preview requests
- Textareas auto-grow up to 400px as content is added
- Auto-grow triggers on toggle open if textarea has content
- Use CSS keyframes (slideDown/slideUp) for 800ms door-like animations
- JS only toggles classes and updates button text at correct timing
- Preview toggle uses native <details> with animated open/close
- Arrow indicators on right side (hide preview ▲ / show preview ▼)
- No-JS fallback preserved (links navigate to dedicated pages)
- CSS grid animation for smooth expand/collapse transitions
- Fade-in animation for namespace dropdown
- Auto-focus textarea on details open (progressive enhancement)
- Falls back gracefully if browser lacks support
- Simplified test_import_graphcomment_format to only verify HTTP response
- Simplified test_import_with_deep_nesting to only verify HTTP response
- Simplified test_import_duplicate_prevention to verify user reuse without node counts
- Fixed test_import_with_locked_group_postfix by using unique namespace
- Fixed test_import_with_invalid_group_postfix by using unique namespace
All 22 tests now pass. Tests were failing due to transaction isolation between
webtest requests and the test's dbsession. Using unique namespaces ensures
tests don't interfere with each other when testing postfix locking behavior.