read.markets/alembic/versions
Giorgio Gilestro f3ac65f8f7 auth: affirmative versioned sign-up acknowledgement (EN + IT)
Replaces the passive "by signing in you agree…" paragraph on /login with
an active un-pre-ticked checkbox over three short statements that the
user actively accepts. Each acceptance is recorded against a code-level
version pointer, so a future wording revision bumps the version and
prompts every user again.

- New app/legal.py::ACKNOWLEDGEMENT_VERSION (currently 1).
- New UserAcknowledgement model + migration 0027 (user_id FK CASCADE,
  version, lang, accepted_at, composite index on user_id+version).
- auth_service: has_acknowledged_current() and record_acknowledgement()
  helpers; POST /login validates the checkbox, falls through to a 400
  with the localised error otherwise, and writes a row iff the user has
  no current-version row (so existing-already-accepted users don't
  produce duplicates).
- GET /login: language detection mirrors the landing's
  detect_public_lang(); ?lang=en|it overrides; stamps the rtm.lang
  cookie; passes the locale dict + version into the template.
- login.html: EN/IT pill, localised lede/banner/legal footer, required
  checkbox in an acknowledgement block, hidden lang+ack_version fields.
  Submit disabled until the box is ticked (UX polish; the server check
  is what carries weight).
- locales/{en,it}.yaml: new auth.ack.* section with TODO(legal) marker.
  Wording matches the brief's substance pending solicitor sign-off.
- tests/test_signup_acknowledgement.py: 10 tests (EN + IT rejection,
  one row per acceptance, displayed-lang recorded, idempotent on
  current version, version-bump writes new row, helper unit tests).

The acknowledgement strengthens the user-civil-claim vector — combined
with the liability cap and the Ltd, it makes "I was misled into thinking
this was advice" much harder to argue. It does NOT move the regulatory
perimeter, which is governed by the content discipline shipped in
47dce1a. Belt-and-braces, not a substitute.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 20:50:38 +02:00
..
0001_initial_schema.py initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
0002_position_name.py initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
0003_log_tone_analysis.py initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
0004_indicator_summaries.py add Eurostat + UK ONS sources; valuation/bubble/economy/bonds groups; aggregate read; market-open header 2026-05-15 23:07:42 +01:00
0005_widen_quote_symbol.py alembic: make migration chain SQLite-compatible (fresh upgrade) 2026-05-28 00:16:09 +02:00
0006_instrument_map.py phase B (1/4): CSV parser + InstrumentMap (T212 shortcode → Yahoo ticker) 2026-05-16 10:53:08 +01:00
0007_users.py phase A: user accounts + session-cookie auth 2026-05-16 11:12:10 +01:00
0008_email_otps.py phase G: data minimisation + passwordless auth + DeepSeek-first LLM 2026-05-18 14:16:57 +01:00
0009_ticker_universe.py phase G: data minimisation + passwordless auth + DeepSeek-first LLM 2026-05-18 14:16:57 +01:00
0010_drop_password.py phase G: data minimisation + passwordless auth + DeepSeek-first LLM 2026-05-18 14:16:57 +01:00
0011_drop_portfolio_tables.py phase G: data minimisation + passwordless auth + DeepSeek-first LLM 2026-05-18 14:16:57 +01:00
0012_headlines_tags.py news: auto-tag headlines + market-aware cadence + filter UI 2026-05-21 23:25:03 +01:00
0013_referrals.py alembic: make migration chain SQLite-compatible (fresh upgrade) 2026-05-28 00:16:09 +02:00
0014_user_credit_until.py phase D milestones 1+2: referral system + paid-access gate 2026-05-21 23:25:35 +01:00
0015_portfolio_sync.py sync: encrypted cloud backup for portfolios + settings UX rework 2026-05-23 16:15:54 +02:00
0016_portfolio_sync_pepper_fp.py sync: detect orphaned blobs (pepper rotation) + fix AESGCM arg order 2026-05-25 12:49:11 +02:00
0017_email_digest.py db: drop redundant user_id index on email_sends 2026-05-25 22:55:33 +02:00
0018_polar_webhook.py alembic: make migration chain SQLite-compatible (fresh upgrade) 2026-05-28 00:16:09 +02:00
0019_stripe.py alembic: make migration chain SQLite-compatible (fresh upgrade) 2026-05-28 00:16:09 +02:00
0020_trial_end.py stripe: per-cadence cooling-off + manage-subscription button 2026-05-26 20:06:19 +02:00
0021_csv_format_template.py alembic: use sa.text() for integer server_defaults in 0021 2026-05-27 12:06:05 +02:00
0022_localization.py alembic: add 0022 localization (users.lang + strategic_log_translations) 2026-05-27 16:53:27 +02:00
0023_lang_index_and_qd_symbol_widen.py alembic: make migration chain SQLite-compatible (fresh upgrade) 2026-05-28 00:16:09 +02:00
0024_ind_summary_translations.py i18n: localize indicator summaries (per-group + aggregate read) 2026-05-27 20:19:47 +02:00
0025_align_translation_columns.py models: align translation column naming + add token counts 2026-05-27 21:18:29 +02:00
0026_compliance_purge_and_audit.py compliance: flag-gate AI portfolio + cloud sync + Stripe; de-risk prompts; harden reviewer 2026-05-29 19:57:12 +02:00
0027_user_acknowledgements.py auth: affirmative versioned sign-up acknowledgement (EN + IT) 2026-05-29 20:50:38 +02:00