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>
134 lines
5.8 KiB
YAML
134 lines
5.8 KiB
YAML
# English copy for the public landing page.
|
|
#
|
|
# Strings that contain inline HTML are rendered with the `safe` filter
|
|
# in the template. Keep markup minimal — <strong>, <em>, and the
|
|
# brand placeholders only.
|
|
|
|
hero:
|
|
tagline: "Understand markets. Don't gamble on them."
|
|
subhead: >-
|
|
Built for investors who want to <strong>act rationally</strong> and
|
|
tune out the high-frequency noise that comes from treating markets
|
|
like a casino. We aggregate cross-asset news and macro signals,
|
|
then write a plain-English read of what the underlying fundamentals
|
|
justify versus what the crowd is doing. Refreshed through the
|
|
trading day. A media service, not a financial one.
|
|
cta_dashboard: "Open dashboard"
|
|
cta_pricing: "See pricing"
|
|
cta_signup: "Sign up free"
|
|
|
|
shot_dashboard:
|
|
alt: "Dashboard preview"
|
|
zoom_hint: "Click to enlarge"
|
|
caption: >-
|
|
The dashboard. An aggregate cross-asset read at the top,
|
|
hand-picked indicator groups underneath. Reading level toggle
|
|
(Novice / Pro) flips every AI-generated panel between
|
|
plain-English and terse-pro framing.
|
|
|
|
features:
|
|
news:
|
|
tag: "News, aggregated"
|
|
title: "Headlines from across the macro universe"
|
|
body: >-
|
|
RSS and per-ticker feeds covering equities, rates, credit, FX,
|
|
commodities, and geopolitics. Every headline is auto-tagged by
|
|
theme so the noise stays as noise and the fundamentals-relevant
|
|
stuff is easy to find. Ingestion follows the trading calendar —
|
|
off-hours stay quiet.
|
|
shot_alt: "News feed with auto-tagged headlines"
|
|
shot_caption: >-
|
|
The news feed. Each headline carries one or more theme tags
|
|
(rates, AI, energy, geopolitics, …) so you can keep the threads
|
|
you care about and mute the ones you don't. Click a tag to
|
|
include; shift-click to exclude.
|
|
indicators:
|
|
tag: "Macro signals"
|
|
title: "A curated cross-asset tape"
|
|
body: >-
|
|
A hand-picked set of indicators across every asset class,
|
|
refreshed hourly during market hours. Each group gets a short
|
|
read that explains what the move <em>means</em>, not what it
|
|
was. Anchored in earnings, policy, valuation — not chart
|
|
patterns.
|
|
shot_alt: "Indicators panel with AI commentary"
|
|
shot_caption: >-
|
|
The indicators panel. Tabs across asset classes (equity, rates,
|
|
commodities, FX, bonds, …); each tab carries a one-paragraph
|
|
'read' written by the model on top of the live prices. The
|
|
numbers anchor the prose so the commentary is checkable, not
|
|
floating.
|
|
strategic:
|
|
tag: "The strategic read"
|
|
title: "Rational vs irrational, every paragraph"
|
|
body: >-
|
|
We tie the day's headlines and the cross-asset signals into a
|
|
single short interpretation. Each paragraph separates
|
|
<strong>rational drivers</strong> (earnings, policy, valuation)
|
|
from <strong>irrational ones</strong> (positioning, narrative,
|
|
flows) and names the gap. Two reading levels: Novice and Pro.
|
|
This is editorial commentary on public data — not a forecast
|
|
and not advice on any investment decision.
|
|
shot_alt: "Strategic log — the editorial AI read"
|
|
shot_caption: >-
|
|
The strategic log. The model writes a fresh interpretation
|
|
through the trading day, taking the previous draft as context
|
|
so it updates rather than starts over. Paid users get a refresh
|
|
every hour; free users get one every six.
|
|
|
|
multilang_callout: >-
|
|
Every AI-generated surface — strategic log, indicator reads, chat,
|
|
daily digest — is available in <strong>English</strong> and
|
|
<strong>Italian</strong>. Toggle the language pill in the header
|
|
and the panels refresh in place; ticker symbols, currency codes
|
|
and numbers stay verbatim across languages.
|
|
|
|
more_views:
|
|
head: "More views"
|
|
chat:
|
|
alt: "Ask follow-up questions against any past log"
|
|
caption: >-
|
|
Ask follow-up questions against any past log. The chat panel
|
|
inherits the log's full context, so you can pull on a thread
|
|
without re-pasting headlines or re-explaining the setup.
|
|
caption_strong: "Ask anything about a log"
|
|
caption_span: "Conversational follow-ups with the day's context loaded."
|
|
|
|
portfolio_blurb: >-
|
|
Drop a portfolio CSV from your broker to see your sector, currency
|
|
and concentration breakdown — computed entirely in your browser.
|
|
Holdings stay in your browser; nothing about them is sent to or
|
|
stored on the server.
|
|
|
|
not_strip:
|
|
head: "What this isn't."
|
|
items:
|
|
- "Not investment advice."
|
|
- "Not trading signals."
|
|
- "Not a day-trading tool."
|
|
- "No buy/sell calls, ever."
|
|
- "No chart-pattern predictions."
|
|
- "Not a regulated service."
|
|
|
|
footer:
|
|
legal: >-
|
|
By signing up you agree to our <a href="/terms">Terms</a> and
|
|
<a href="/privacy">Privacy notice</a>, and confirm you've read
|
|
the <a href="/disclaimer">financial disclaimer</a>.
|
|
|
|
meta:
|
|
description: "Understand markets. Don't gamble on them."
|
|
|
|
# TODO(legal): final wording pending solicitor sign-off. Bumping
|
|
# ACKNOWLEDGEMENT_VERSION (app/legal.py) re-prompts every existing user
|
|
# on next sign-in and writes a fresh row at the new version.
|
|
auth:
|
|
ack:
|
|
heading: "Before you create an account, please confirm:"
|
|
items:
|
|
- "This service is editorial and educational commentary on public market data. It is not financial, investment, or tax advice and is not a personal recommendation."
|
|
- "The operator is not authorised or regulated to provide investment advice. Nothing here is a recommendation to buy, sell, or hold any investment."
|
|
- "I make my own investment decisions and am solely responsible for them. For personal advice I will consult a regulated adviser."
|
|
checkbox_label: "I have read and accept these statements."
|
|
error_required: "Please tick the box to confirm the acknowledgement before continuing."
|
|
lang_switch_aria: "Language"
|