Add legal policy pages and shared layout component
- Add Cookie Policy view documenting essential cookies (session, CSRF, remember_me, fa_location) and cookieless Umami analytics - Add Privacy Policy view covering UK GDPR compliance, data categories, lawful bases, processors, retention, and user rights - Add Refund & Cancellation Policy view explaining 14-day cooling-off period under Consumer Contracts Regulations 2013 and express-consent flow - Add Terms of Service view defining account rules, subscription billing, and governing law - Create shared legal layout component with FuelAlert header, footer with cross-links, and consistent typography - Add feature tests covering all four legal pages and their cross-links - All policies include placeholders for ICO registration number, email, and hosting/email providers pending production config
This commit is contained in:
403
docs/superpowers/specs/legal-pages-spec.md
Normal file
403
docs/superpowers/specs/legal-pages-spec.md
Normal file
@@ -0,0 +1,403 @@
|
||||
# FuelAlert — Legal Pages Spec
|
||||
|
||||
## Context for Claude Code
|
||||
|
||||
You are generating four legal pages for **FuelAlert**, a UK consumer subscription web/mobile app that shows real-time UK fuel prices and forecasts.
|
||||
|
||||
### Reference comparable (structural check, NOT for copying)
|
||||
|
||||
A near-identical business already exists and has competent legal pages: **Fuel Finder UK** at https://www.fuel-finder.uk, operated by Scott Benson as a UK sole trader. Same business model, same data sources, same jurisdiction.
|
||||
|
||||
**Use it ONLY as a structural sanity check.** Do not copy any text. Their content is copyrighted and their specific processors / retention periods / business decisions are not FuelAlert's.
|
||||
|
||||
What Fuel Finder UK does well that this spec already incorporates:
|
||||
- Explicit sole trader disclosure naming the operator
|
||||
- Named ICO registration number in the Privacy Policy
|
||||
- Specific named processors (Stripe, hosting provider, email provider, analytics, mapping services) with what data flows to each
|
||||
- Strong price-accuracy disclaimer in Terms ("prices may not reflect real-time changes, always verify at the pump")
|
||||
- "AS IS" / "AS AVAILABLE" basis with liability limitations
|
||||
- ICO complaint route clearly stated
|
||||
- Account deletion flow that cancels paid subscription first
|
||||
|
||||
What FuelAlert must do BETTER than Fuel Finder UK:
|
||||
- **Standalone Refund & Cancellation Policy page** — Fuel Finder UK appears to bundle this into Terms. Stripe specifically asks for a refund policy; keep it as a separate page at `/legal/refund`.
|
||||
- **Express-consent checkbox at subscription checkout** for the 14-day cooling-off period under Consumer Contracts Regulations 2013 (see Refund Policy section below). This is the single most important implementation detail in the entire spec.
|
||||
|
||||
If you find yourself generating content that overlaps verbatim with Fuel Finder UK or any other site, stop and rewrite in your own words. Legal pages are copyrighted works.
|
||||
|
||||
**Business operator (data controller):**
|
||||
- Name: Ovidiu Ungureanu
|
||||
- Trading as: FuelAlert
|
||||
- Status: Sole trader (not a limited company — do not use "Ltd", "Limited", or any corporate form)
|
||||
- Location: Peterborough, United Kingdom
|
||||
- Contact email: [hello@fuelalert.co.uk]
|
||||
- ICO registration number: [PLACEHOLDER: ZAxxxxxxx — Ovidiu to register at ico.org.uk before launch, fee ~£40/yr]
|
||||
|
||||
**Service:**
|
||||
- UK fuel price comparison and forecasting
|
||||
- Free tier + two paid subscription tiers: Daily (£0.99/mo) and Smart (£2.49/mo); annual billing also offered
|
||||
- Data sources: UK government Fuel Finder / Pump Watch open data, ONS Postcode Directory (OGL/Crown Copyright)
|
||||
- Processes: email address, postcode/location data, account credentials, payment data (via Stripe), usage telemetry
|
||||
|
||||
**Jurisdiction:**
|
||||
- England and Wales
|
||||
- Consumer law: Consumer Rights Act 2015, Consumer Contracts (Information, Cancellation and Additional Charges) Regulations 2013 ("CCRs")
|
||||
- Data protection: UK GDPR + Data Protection Act 2018, PECR for cookies/marketing
|
||||
- Digital markets: Digital Markets, Competition and Consumers Act 2024 ("DMCC")
|
||||
|
||||
**Tech stack & integration:**
|
||||
- Laravel + Blade for server-rendered pages (NOT Vue components — these must render in raw HTML for Stripe reviewers and SEO)
|
||||
- Route prefix: `/legal/*`
|
||||
- Layout: extend the existing site layout but with a readable prose container (max-width ~720px, generous line-height)
|
||||
- Each page has a `last_updated` date in front matter — set to today
|
||||
- All pages must be linkable from the footer and accessible without JavaScript
|
||||
|
||||
### ⚠️ CRITICAL: Server-rendered Blade only, NOT Vue
|
||||
|
||||
The rest of this application is a Vue SPA. **That is irrelevant for these pages.** The legal pages must be server-rendered Blade templates.
|
||||
|
||||
Rules:
|
||||
- Files live at `resources/views/legal/{name}.blade.php` — never `.vue`
|
||||
- Body content must be plain HTML with Blade directives (`@extends`, `@section`, `{{ }}`)
|
||||
- No Vue components anywhere in the page body — no custom tags like `<legal-privacy-page>`, no `<div id="app">`, no Vue mounting points
|
||||
- No client-side rendering for the legal content itself — Alpine.js is acceptable only for the cookie banner show/hide behaviour, nothing else
|
||||
- Pages must work fully with JavaScript disabled
|
||||
|
||||
**Verification test (run after generation):**
|
||||
|
||||
```bash
|
||||
curl -s https://[host]/legal/privacy | grep -i "data controller"
|
||||
curl -s https://[host]/legal/terms | grep -i "subscription"
|
||||
curl -s https://[host]/legal/refund | grep -i "14-day"
|
||||
curl -s https://[host]/legal/cookies | grep -i "essential"
|
||||
```
|
||||
|
||||
Each command must return matching lines from the raw HTML response. If any returns empty, the page has been built as a client-rendered component and must be redone as Blade.
|
||||
|
||||
If you find yourself reaching for `<script>` tags, Vue single-file components, or any pattern that requires the browser to execute JS before content appears — stop and use plain Blade instead.
|
||||
|
||||
---
|
||||
|
||||
## Pages to generate
|
||||
|
||||
1. `/legal/privacy` — Privacy Policy
|
||||
2. `/legal/terms` — Terms of Service
|
||||
3. `/legal/refund` — Refund & Cancellation Policy (can be a section of Terms, but a separate page is cleaner for Stripe review)
|
||||
4. `/legal/cookies` — Cookie Policy (paired with a real consent banner — see separate section)
|
||||
|
||||
---
|
||||
|
||||
## 1. Privacy Policy (`/legal/privacy`)
|
||||
|
||||
### Required sections, in order:
|
||||
|
||||
**1. Who we are**
|
||||
- Identify Ovidiu Ungureanu as data controller, trading as FuelAlert
|
||||
- Sole trader status, Peterborough address (use generic "Peterborough, UK" unless a registered business address is provided)
|
||||
- ICO registration number
|
||||
- Contact email for privacy queries
|
||||
|
||||
**2. What data we collect**
|
||||
Break into clear subsections:
|
||||
- *Account data*: email, hashed password, account creation date
|
||||
- *Location data*: postcodes entered, optional precise GPS if granted, derived location for nearby-station queries
|
||||
- *Payment data*: handled by Stripe; FuelAlert does NOT store card numbers. Stripe customer ID and subscription metadata only.
|
||||
- *Usage data*: features used, queries made, price alerts configured (for service delivery and improvement)
|
||||
- *Technical data*: IP address, browser type, device type (for security and analytics)
|
||||
- *Marketing preferences*: only if user opts in
|
||||
|
||||
**3. Lawful basis for processing**
|
||||
For each category, state the UK GDPR Article 6 basis:
|
||||
- Account + service delivery: **contract** (Art. 6(1)(b))
|
||||
- Payment processing: **contract**
|
||||
- Security/fraud prevention: **legitimate interests** (Art. 6(1)(f))
|
||||
- Analytics/product improvement: **legitimate interests**, with opt-out via cookie banner
|
||||
- Marketing emails: **consent** (Art. 6(1)(a))
|
||||
|
||||
**4. How we use your data**
|
||||
Bullet list, plain English. Tie back to the lawful basis for each use.
|
||||
|
||||
**5. Who we share data with (processors)**
|
||||
Named list — be specific:
|
||||
- **Stripe** (payment processing) — refer to Stripe's privacy policy
|
||||
- **[Hosting provider, e.g. Hetzner]** (infrastructure) — EU-based, note location
|
||||
- **[Email provider, e.g. Fastmail / Postmark]** (transactional email)
|
||||
- **[Analytics, e.g. Plausible]** — if used; if self-hosted, say so
|
||||
- State that we do NOT sell data to third parties
|
||||
|
||||
**6. International transfers**
|
||||
- State whether any processors are outside the UK/EEA (Stripe has US operations)
|
||||
- Reference appropriate safeguards: Standard Contractual Clauses (SCCs) and UK International Data Transfer Addendum
|
||||
|
||||
**7. How long we keep data**
|
||||
- Active account data: while account is active + 12 months after closure
|
||||
- Payment records: 6 years (HMRC requirement for sole traders)
|
||||
- Marketing data: until consent is withdrawn
|
||||
- Logs/analytics: max 24 months
|
||||
|
||||
**8. Your rights under UK GDPR**
|
||||
List all eight rights with one-line explanations:
|
||||
- Right of access
|
||||
- Right to rectification
|
||||
- Right to erasure ("right to be forgotten")
|
||||
- Right to restrict processing
|
||||
- Right to data portability
|
||||
- Right to object
|
||||
- Rights related to automated decision-making (state we do NOT make solely automated decisions with legal effect)
|
||||
- Right to withdraw consent
|
||||
|
||||
Explain how to exercise rights (email to the contact address, response within one month).
|
||||
|
||||
**9. Cookies**
|
||||
Brief mention with link to the dedicated Cookie Policy.
|
||||
|
||||
**10. Security**
|
||||
Plain-English summary: HTTPS, hashed passwords, encrypted database fields where appropriate, access controls, regular updates. Don't overpromise ("bank-grade" etc. — meaningless and creates liability).
|
||||
|
||||
**11. Children**
|
||||
Service is not directed at under-16s; we do not knowingly collect data from children.
|
||||
|
||||
**12. Complaints**
|
||||
Right to complain to the ICO: ico.org.uk, 0303 123 1113. Encourage contacting FuelAlert first.
|
||||
|
||||
**13. Changes to this policy**
|
||||
We will notify users of material changes by email; non-material changes shown by updated "Last updated" date.
|
||||
|
||||
**14. Contact**
|
||||
Email address for privacy queries.
|
||||
|
||||
### Tone & style
|
||||
- Plain English, Hemingway readability score ~grade 8
|
||||
- No legalese where avoidable
|
||||
- Use "we" / "you"
|
||||
- Short paragraphs, lots of headings, scannable
|
||||
|
||||
---
|
||||
|
||||
## 2. Terms of Service (`/legal/terms`)
|
||||
|
||||
### Required sections, in order:
|
||||
|
||||
**1. About these terms**
|
||||
- Who FuelAlert is (sole trader disclosure)
|
||||
- These terms form a contract between you and Ovidiu Ungureanu trading as FuelAlert
|
||||
- By using the service you agree to these terms
|
||||
- Governing law: England and Wales
|
||||
|
||||
**2. The service**
|
||||
- What FuelAlert does
|
||||
- Free tier and paid tier descriptions
|
||||
- We may add, remove, or change features with reasonable notice
|
||||
|
||||
**3. Your account**
|
||||
- Eligibility: 18+, UK resident, accurate information required
|
||||
- One account per person
|
||||
- You're responsible for keeping login credentials secure
|
||||
- We may suspend accounts for breach of these terms
|
||||
|
||||
**4. Subscriptions, billing and payment**
|
||||
This is the section Stripe cares most about. Cover:
|
||||
- Prices (link to /pricing) — currently £0.99/mo Daily, £2.49/mo Smart, with annual discount
|
||||
- Billing cycle: monthly or annual, charged in advance
|
||||
- **Auto-renewal**: subscriptions auto-renew at the end of each period at the then-current price, until cancelled
|
||||
- Payment method: card via Stripe; you authorise FuelAlert (via Stripe) to charge your method on each renewal
|
||||
- Failed payments: we'll retry and notify you; persistent failure suspends paid features
|
||||
- Price changes: 30 days' notice by email before any price increase takes effect on renewal; you may cancel before the increase
|
||||
- VAT: prices include UK VAT where applicable (sole traders below the VAT threshold do not charge VAT — clarify FuelAlert's current status)
|
||||
|
||||
**5. Cancellation and refunds**
|
||||
Cross-reference the Refund Policy. Summarise:
|
||||
- You can cancel at any time from your account settings
|
||||
- Cancellation stops the next renewal; you keep access until the end of the current billing period
|
||||
- 14-day right to cancel for new subscribers (see Refund Policy for the express-consent mechanism that affects this)
|
||||
|
||||
**6. Acceptable use**
|
||||
You agree not to:
|
||||
- Scrape, reverse-engineer, or bulk-extract data from the service
|
||||
- Resell or redistribute price data
|
||||
- Use the service for any unlawful purpose
|
||||
- Attempt to compromise security
|
||||
- Create automated queries beyond normal personal use
|
||||
|
||||
**7. Accuracy of price data — IMPORTANT**
|
||||
This is your liability shield. Say clearly:
|
||||
- Prices are sourced from official UK government data feeds (Pump Watch / Fuel Finder) and refreshed periodically
|
||||
- We make reasonable efforts to display accurate prices but **cannot guarantee** prices are correct at the moment you arrive at a station
|
||||
- Stations may change prices between data feed updates
|
||||
- FuelAlert is not liable for losses arising from inaccurate price data (wasted journey, fuel cost differences, etc.)
|
||||
- Always confirm the price at the pump before fuelling
|
||||
|
||||
**8. Forecasts and predictions**
|
||||
- Forecasts are informational only and not financial advice
|
||||
- Past trends do not guarantee future prices
|
||||
- We do not warrant the accuracy of any forecast
|
||||
|
||||
**9. Intellectual property**
|
||||
- The FuelAlert name, logo, software, and original content are owned by Ovidiu Ungureanu
|
||||
- Underlying fuel price data is owned by the respective retailers and published under government open data schemes; ONS Postcode Directory data is © Crown Copyright, used under Open Government Licence v3.0
|
||||
- You get a limited, non-exclusive, revocable licence to use the service for personal, non-commercial purposes (or commercial fleet use if on a Fleet plan)
|
||||
|
||||
**10. Third-party services**
|
||||
We use Stripe for payments. Your use of Stripe is also subject to Stripe's terms.
|
||||
|
||||
**11. Limitation of liability**
|
||||
- We don't exclude liability for death/personal injury caused by negligence, fraud, or anything that can't be excluded under UK consumer law
|
||||
- We exclude liability for indirect, consequential, or business losses
|
||||
- For consumers using the paid service, our total liability in any 12-month period is capped at the amount you paid in subscription fees in that period
|
||||
- We don't accept liability for issues caused by third-party services we depend on (Stripe outage, data feed outage, etc.)
|
||||
|
||||
**12. Termination**
|
||||
- You can stop using the service and close your account at any time
|
||||
- We can terminate access for serious breach of these terms, with notice where reasonable
|
||||
- On termination, paid sections 4–11 of these terms survive
|
||||
|
||||
**13. Changes to these terms**
|
||||
We may update these terms; material changes notified by email at least 14 days before they take effect.
|
||||
|
||||
**14. Disputes**
|
||||
- Try to resolve directly by contacting us first
|
||||
- These terms are governed by the laws of England and Wales; courts of England and Wales have non-exclusive jurisdiction
|
||||
- Consumers retain the right to bring proceedings in their country of residence
|
||||
- Reference to alternative dispute resolution if applicable
|
||||
|
||||
**15. Contact**
|
||||
Email address.
|
||||
|
||||
---
|
||||
|
||||
## 3. Refund & Cancellation Policy (`/legal/refund`)
|
||||
|
||||
This page is required by Stripe specifically and by UK consumer law. Keep it short and clear.
|
||||
|
||||
### Required sections:
|
||||
|
||||
**1. Your 14-day right to cancel (cooling-off period)**
|
||||
- Under the Consumer Contracts Regulations 2013, you have 14 days from the date you subscribe to cancel without giving a reason
|
||||
- This applies to **new subscribers only**; not subsequent renewals
|
||||
|
||||
**2. Express consent to start the service immediately — CRITICAL CLAUSE**
|
||||
- When you subscribe, you can choose to start using the paid features immediately
|
||||
- By doing so, you expressly acknowledge that you **lose your right to cancel** once the service has been fully supplied (i.e. once you've used the paid features within the 14-day window)
|
||||
- If you cancel before using the paid features, you receive a full refund
|
||||
- If you cancel within 14 days having used some paid features, we may reduce the refund proportionally to reflect usage
|
||||
|
||||
**Implementation note for the signup flow:** the express consent must be an unticked checkbox at checkout, with explicit text. Do not pre-tick it. Suggested wording for the checkbox label:
|
||||
> "I want my subscription to start immediately. I understand that by using paid features within the 14-day cooling-off period, I will lose my right to cancel under the Consumer Contracts Regulations 2013."
|
||||
|
||||
**3. How to cancel**
|
||||
- From your account: Settings → Subscription → Cancel
|
||||
- Or by emailing the contact address
|
||||
- Cancellation is effective at the end of the current billing period unless you exercise the 14-day right above
|
||||
|
||||
**4. Refunds outside the 14-day period**
|
||||
- After 14 days, subscription fees are non-refundable for the remainder of the period you paid for
|
||||
- You keep access until the end of the period
|
||||
- We may issue discretionary refunds in cases of service failure or where required by law
|
||||
|
||||
**5. Annual subscriptions**
|
||||
- Same 14-day right applies
|
||||
- After 14 days, annual fees are non-refundable; no pro-rata refund for unused months
|
||||
|
||||
**6. Failed payments and involuntary cancellation**
|
||||
- If your payment fails, we'll retry and notify you
|
||||
- Paid features suspend after [N] failed retries
|
||||
- Your account is not deleted; you can resume by updating payment
|
||||
|
||||
**7. How long refunds take**
|
||||
- Refunds are issued to the original payment method within 5–10 business days of approval
|
||||
|
||||
**8. Contact**
|
||||
Email address for refund requests.
|
||||
|
||||
---
|
||||
|
||||
## 4. Cookie Policy (`/legal/cookies`)
|
||||
|
||||
### Required sections:
|
||||
|
||||
**1. What cookies are**
|
||||
One short paragraph.
|
||||
|
||||
**2. Cookies we use**
|
||||
Table format with columns: Name | Purpose | Duration | Type (Essential / Analytics / Marketing).
|
||||
|
||||
Categories to include:
|
||||
- **Essential**: session, CSRF, authentication, cookie-consent preference itself — these do not require consent under PECR
|
||||
- **Analytics**: only if you use them; name them specifically (Plausible is cookie-less in many configs, GA4 uses several)
|
||||
- **Marketing**: only if you run any — likely none at launch
|
||||
|
||||
--- ignore for now. need to decide what tool to use for this
|
||||
|
||||
**3. Your choices**
|
||||
- You can accept, decline, or customise non-essential cookies via the consent banner
|
||||
- You can change your choice at any time via "Cookie Settings" in the footer
|
||||
- Most browsers also let you block cookies — link to ICO guidance on managing cookies
|
||||
|
||||
**4. Changes to this policy**
|
||||
Standard wording.
|
||||
|
||||
**5. Contact**
|
||||
Email.
|
||||
|
||||
---
|
||||
|
||||
## Cookie consent banner (separate component)
|
||||
|
||||
Implement as a Blade component, server-rendered, that:
|
||||
|
||||
- Appears on first visit
|
||||
- Has three buttons: **Accept all**, **Reject all**, **Customise**
|
||||
- "Customise" expands to checkboxes per category (Essential — locked on; Analytics; Marketing if applicable)
|
||||
- Stores choice in a first-party cookie (`fa_cookie_consent`) for 12 months
|
||||
- **Blocks non-essential scripts from loading until consent is given** — this is the critical bit. Use a tag manager pattern or conditional Blade includes; do NOT load Google Analytics, etc. before consent.
|
||||
- Persistent "Cookie Settings" link in the footer reopens the customise panel
|
||||
|
||||
PECR / ICO require equal prominence for accept and reject. Don't make "Reject" smaller or harder to find.
|
||||
|
||||
---
|
||||
|
||||
## Implementation notes for Claude Code
|
||||
|
||||
1. **Create Laravel routes** in `routes/web.php`:
|
||||
```php
|
||||
Route::view('/legal/privacy', 'legal.privacy')->name('legal.privacy');
|
||||
Route::view('/legal/terms', 'legal.terms')->name('legal.terms');
|
||||
Route::view('/legal/refund', 'legal.refund')->name('legal.refund');
|
||||
Route::view('/legal/cookies', 'legal.cookies')->name('legal.cookies');
|
||||
```
|
||||
|
||||
2. **Create Blade layout** `resources/views/layouts/legal.blade.php` extending the main site layout, with a narrow prose container.
|
||||
|
||||
3. **Each page** at `resources/views/legal/{name}.blade.php` should:
|
||||
- Set page title
|
||||
- Set meta description (short summary, ~150 chars)
|
||||
- Render the content in semantic HTML (h1, h2, h3, ul, ol, table where appropriate)
|
||||
- Show "Last updated: [date]" at top
|
||||
- Use Blade `@section` for content
|
||||
|
||||
4. **Update footer** to link to all four legal pages with `route()` helpers. Replace any existing "Cookie Settings" link with a button that opens the consent banner customise panel.
|
||||
|
||||
5. **Cookie banner component** at `resources/views/components/cookie-banner.blade.php` — include in main layout, with Alpine.js or vanilla JS for show/hide logic. Must be functional with JavaScript disabled (degrade to "you can change cookie settings in your browser" message).
|
||||
|
||||
6. **Do NOT** auto-generate the ICO registration number or contact email. Leave clear `[PLACEHOLDER: ...]` markers throughout for Ovidiu to fill in before deployment.
|
||||
|
||||
7. **Do NOT** include claims that aren't true yet — if uncertain, use a `[PLACEHOLDER: verify before launch]` marker rather than guessing.
|
||||
|
||||
8. **At the top of each generated file**, add a comment:
|
||||
```
|
||||
{{-- DRAFT: Generated [date]. Review by UK-qualified solicitor recommended before launch. --}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pre-launch checklist for Ovidiu (not for Claude Code)
|
||||
|
||||
- [ ] Register with the ICO (ico.org.uk) and obtain registration number — required by law for processing personal data commercially
|
||||
- [ ] Replace all `[PLACEHOLDER: ...]` markers
|
||||
- [ ] Confirm hosting provider and processors named in the Privacy Policy are accurate
|
||||
- [ ] Test the cookie banner: does it block non-essential scripts before consent?
|
||||
- [ ] Test the signup flow: is the express-consent checkbox unticked by default?
|
||||
- [ ] Test account cancellation: does it work end-to-end?
|
||||
- [ ] Have a UK-qualified solicitor review (or use Termly/iubenda as a sanity check)
|
||||
- [ ] Set `last_updated` dates to the actual go-live date
|
||||
- [ ] Submit to Stripe with the live URL
|
||||
Reference in New Issue
Block a user