fix(subscriptions): trial 14 dagar konsekvent i UI/docs/legal/butik

TRIAL_DAYS var redan 14 i koden men auth.trialNote (12 sprak), butiksmetadata, juridik-utkast, API-ref, exec-summary och UX-doc sa 7. Nu 14 overallt. Rorde EJ icke-trial 7-dagar (inbjudningslank, backup, S3-lifecycle, grace, retention). Beslut: Johan (battre onboarding).
This commit is contained in:
Claude
2026-08-17 17:04:00 +00:00
parent cacca3481c
commit 88876a24b7
20 changed files with 21 additions and 21 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Skift adgangskode", "auth.resetSubmit": "Skift adgangskode",
"auth.resetTitle": "Vælg en ny adgangskode", "auth.resetTitle": "Vælg en ny adgangskode",
"auth.resetTokenPlaceholder": "Indsæt koden fra e-mailen", "auth.resetTokenPlaceholder": "Indsæt koden fra e-mailen",
"auth.trialNote": "7 dages fuld adgang uden kort.", "auth.trialNote": "14 dages fuld adgang uden kort.",
"auth.verifyDoneBody": "Tak! Din konto er nu verificeret.", "auth.verifyDoneBody": "Tak! Din konto er nu verificeret.",
"auth.verifyDoneTitle": "E-mail bekræftet", "auth.verifyDoneTitle": "E-mail bekræftet",
"auth.verifyFailedBody": "Linket er ugyldigt eller udløbet. Anmod om et nyt fra profilen.", "auth.verifyFailedBody": "Linket er ugyldigt eller udløbet. Anmod om et nyt fra profilen.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Passwort ändern", "auth.resetSubmit": "Passwort ändern",
"auth.resetTitle": "Neues Passwort wählen", "auth.resetTitle": "Neues Passwort wählen",
"auth.resetTokenPlaceholder": "Code aus der E-Mail einfügen", "auth.resetTokenPlaceholder": "Code aus der E-Mail einfügen",
"auth.trialNote": "7 Tage voller Zugriff ohne Karte.", "auth.trialNote": "14 Tage voller Zugriff ohne Karte.",
"auth.verifyDoneBody": "Danke! Dein Konto ist jetzt verifiziert.", "auth.verifyDoneBody": "Danke! Dein Konto ist jetzt verifiziert.",
"auth.verifyDoneTitle": "E-Mail bestätigt", "auth.verifyDoneTitle": "E-Mail bestätigt",
"auth.verifyFailedBody": "Der Link ist ungültig oder abgelaufen. Fordere im Profil einen neuen an.", "auth.verifyFailedBody": "Der Link ist ungültig oder abgelaufen. Fordere im Profil einen neuen an.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Change password", "auth.resetSubmit": "Change password",
"auth.resetTitle": "Choose a new password", "auth.resetTitle": "Choose a new password",
"auth.resetTokenPlaceholder": "Paste the code from the email", "auth.resetTokenPlaceholder": "Paste the code from the email",
"auth.trialNote": "7 days of full access no card required.", "auth.trialNote": "14 days of full access no card required.",
"auth.verifyDoneBody": "Thanks! Your account is now verified.", "auth.verifyDoneBody": "Thanks! Your account is now verified.",
"auth.verifyDoneTitle": "Email confirmed", "auth.verifyDoneTitle": "Email confirmed",
"auth.verifyFailedBody": "The link is invalid or has expired. Request a new one from your profile.", "auth.verifyFailedBody": "The link is invalid or has expired. Request a new one from your profile.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Cambiar contraseña", "auth.resetSubmit": "Cambiar contraseña",
"auth.resetTitle": "Elige una nueva contraseña", "auth.resetTitle": "Elige una nueva contraseña",
"auth.resetTokenPlaceholder": "Pega el código del correo", "auth.resetTokenPlaceholder": "Pega el código del correo",
"auth.trialNote": "7 días de acceso completo sin tarjeta.", "auth.trialNote": "14 días de acceso completo sin tarjeta.",
"auth.verifyDoneBody": "¡Gracias! Tu cuenta está verificada.", "auth.verifyDoneBody": "¡Gracias! Tu cuenta está verificada.",
"auth.verifyDoneTitle": "Correo confirmado", "auth.verifyDoneTitle": "Correo confirmado",
"auth.verifyFailedBody": "El enlace no es válido o ha caducado. Solicita uno nuevo desde tu perfil.", "auth.verifyFailedBody": "El enlace no es válido o ha caducado. Solicita uno nuevo desde tu perfil.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Vaihda salasana", "auth.resetSubmit": "Vaihda salasana",
"auth.resetTitle": "Valitse uusi salasana", "auth.resetTitle": "Valitse uusi salasana",
"auth.resetTokenPlaceholder": "Liitä koodi sähköpostista", "auth.resetTokenPlaceholder": "Liitä koodi sähköpostista",
"auth.trialNote": "7 päivää täyttä käyttöä ilman korttia.", "auth.trialNote": "14 päivää täyttä käyttöä ilman korttia.",
"auth.verifyDoneBody": "Kiitos! Tilisi on nyt vahvistettu.", "auth.verifyDoneBody": "Kiitos! Tilisi on nyt vahvistettu.",
"auth.verifyDoneTitle": "Sähköposti vahvistettu", "auth.verifyDoneTitle": "Sähköposti vahvistettu",
"auth.verifyFailedBody": "Linkki on virheellinen tai vanhentunut. Pyydä uusi profiilista.", "auth.verifyFailedBody": "Linkki on virheellinen tai vanhentunut. Pyydä uusi profiilista.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Changer le mot de passe", "auth.resetSubmit": "Changer le mot de passe",
"auth.resetTitle": "Choisissez un nouveau mot de passe", "auth.resetTitle": "Choisissez un nouveau mot de passe",
"auth.resetTokenPlaceholder": "Collez le code reçu par e-mail", "auth.resetTokenPlaceholder": "Collez le code reçu par e-mail",
"auth.trialNote": "7 jours d'accès complet sans carte.", "auth.trialNote": "14 jours d'accès complet sans carte.",
"auth.verifyDoneBody": "Merci ! Votre compte est vérifié.", "auth.verifyDoneBody": "Merci ! Votre compte est vérifié.",
"auth.verifyDoneTitle": "E-mail confirmé", "auth.verifyDoneTitle": "E-mail confirmé",
"auth.verifyFailedBody": "Le lien est invalide ou expiré. Demandez-en un nouveau depuis votre profil.", "auth.verifyFailedBody": "Le lien est invalide ou expiré. Demandez-en un nouveau depuis votre profil.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Cambia password", "auth.resetSubmit": "Cambia password",
"auth.resetTitle": "Scegli una nuova password", "auth.resetTitle": "Scegli una nuova password",
"auth.resetTokenPlaceholder": "Incolla il codice dall'email", "auth.resetTokenPlaceholder": "Incolla il codice dall'email",
"auth.trialNote": "7 giorni di accesso completo senza carta.", "auth.trialNote": "14 giorni di accesso completo senza carta.",
"auth.verifyDoneBody": "Grazie! Il tuo account è verificato.", "auth.verifyDoneBody": "Grazie! Il tuo account è verificato.",
"auth.verifyDoneTitle": "Email confermata", "auth.verifyDoneTitle": "Email confermata",
"auth.verifyFailedBody": "Il link non è valido o è scaduto. Richiedine uno nuovo dal profilo.", "auth.verifyFailedBody": "Il link non è valido o è scaduto. Richiedine uno nuovo dal profilo.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Bytt passord", "auth.resetSubmit": "Bytt passord",
"auth.resetTitle": "Velg et nytt passord", "auth.resetTitle": "Velg et nytt passord",
"auth.resetTokenPlaceholder": "Lim inn koden fra e-posten", "auth.resetTokenPlaceholder": "Lim inn koden fra e-posten",
"auth.trialNote": "7 dager full tilgang uten kort.", "auth.trialNote": "14 dager full tilgang uten kort.",
"auth.verifyDoneBody": "Takk! Kontoen din er verifisert.", "auth.verifyDoneBody": "Takk! Kontoen din er verifisert.",
"auth.verifyDoneTitle": "E-post bekreftet", "auth.verifyDoneTitle": "E-post bekreftet",
"auth.verifyFailedBody": "Lenken er ugyldig eller utløpt. Be om en ny fra profilen.", "auth.verifyFailedBody": "Lenken er ugyldig eller utløpt. Be om en ny fra profilen.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Wachtwoord wijzigen", "auth.resetSubmit": "Wachtwoord wijzigen",
"auth.resetTitle": "Kies een nieuw wachtwoord", "auth.resetTitle": "Kies een nieuw wachtwoord",
"auth.resetTokenPlaceholder": "Plak de code uit de e-mail", "auth.resetTokenPlaceholder": "Plak de code uit de e-mail",
"auth.trialNote": "7 dagen volledige toegang zonder kaart.", "auth.trialNote": "14 dagen volledige toegang zonder kaart.",
"auth.verifyDoneBody": "Bedankt! Je account is geverifieerd.", "auth.verifyDoneBody": "Bedankt! Je account is geverifieerd.",
"auth.verifyDoneTitle": "E-mail bevestigd", "auth.verifyDoneTitle": "E-mail bevestigd",
"auth.verifyFailedBody": "De link is ongeldig of verlopen. Vraag een nieuwe aan via je profiel.", "auth.verifyFailedBody": "De link is ongeldig of verlopen. Vraag een nieuwe aan via je profiel.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Zmień hasło", "auth.resetSubmit": "Zmień hasło",
"auth.resetTitle": "Wybierz nowe hasło", "auth.resetTitle": "Wybierz nowe hasło",
"auth.resetTokenPlaceholder": "Wklej kod z e-maila", "auth.resetTokenPlaceholder": "Wklej kod z e-maila",
"auth.trialNote": "7 dni pełnego dostępu bez karty.", "auth.trialNote": "14 dni pełnego dostępu bez karty.",
"auth.verifyDoneBody": "Dziękujemy! Twoje konto jest zweryfikowane.", "auth.verifyDoneBody": "Dziękujemy! Twoje konto jest zweryfikowane.",
"auth.verifyDoneTitle": "E-mail potwierdzony", "auth.verifyDoneTitle": "E-mail potwierdzony",
"auth.verifyFailedBody": "Link jest nieprawidłowy lub wygasł. Poproś o nowy w profilu.", "auth.verifyFailedBody": "Link jest nieprawidłowy lub wygasł. Poproś o nowy w profilu.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Alterar palavra-passe", "auth.resetSubmit": "Alterar palavra-passe",
"auth.resetTitle": "Escolha uma nova palavra-passe", "auth.resetTitle": "Escolha uma nova palavra-passe",
"auth.resetTokenPlaceholder": "Cole o código do e-mail", "auth.resetTokenPlaceholder": "Cole o código do e-mail",
"auth.trialNote": "7 dias de acesso completo sem cartão.", "auth.trialNote": "14 dias de acesso completo sem cartão.",
"auth.verifyDoneBody": "Obrigado! A sua conta está verificada.", "auth.verifyDoneBody": "Obrigado! A sua conta está verificada.",
"auth.verifyDoneTitle": "E-mail confirmado", "auth.verifyDoneTitle": "E-mail confirmado",
"auth.verifyFailedBody": "O link é inválido ou expirou. Peça um novo no perfil.", "auth.verifyFailedBody": "O link é inválido ou expirou. Peça um novo no perfil.",
+1 -1
View File
@@ -20,7 +20,7 @@
"auth.resetSubmit": "Byt lösenord", "auth.resetSubmit": "Byt lösenord",
"auth.resetTitle": "Välj nytt lösenord", "auth.resetTitle": "Välj nytt lösenord",
"auth.resetTokenPlaceholder": "Klistra in koden från mejlet", "auth.resetTokenPlaceholder": "Klistra in koden från mejlet",
"auth.trialNote": "7 dagars full tillgång inget kort behövs.", "auth.trialNote": "14 dagars full tillgång inget kort behövs.",
"auth.verifyDoneBody": "Tack! Ditt konto är nu verifierat.", "auth.verifyDoneBody": "Tack! Ditt konto är nu verifierat.",
"auth.verifyDoneTitle": "E-postadressen är bekräftad", "auth.verifyDoneTitle": "E-postadressen är bekräftad",
"auth.verifyFailedBody": "Länken är ogiltig eller har gått ut. Begär en ny från profilen.", "auth.verifyFailedBody": "Länken är ogiltig eller har gått ut. Begär en ny från profilen.",
+1 -1
View File
@@ -46,7 +46,7 @@ och tolkar men hittar aldrig på vilket gör produkten trovärdig nog för a
## Affärsvärde ## Affärsvärde
Prenumeration via App Store/Google Play: **Household 79 kr**, **Family 129 kr**, Prenumeration via App Store/Google Play: **Household 79 kr**, **Family 129 kr**,
**Large Household 169 kr** per månad, 7 dagars fri provperiod utan kort, användbar **Large Household 169 kr** per månad, 14 dagars fri provperiod utan kort, användbar
gratisnivå (10 AI-skanningar/mån) som behåller användare i tratten. gratisnivå (10 AI-skanningar/mån) som behåller användare i tratten.
Ett genomsnittligt svenskt barnhushåll slänger mat för tusenlappar per år och lägger Ett genomsnittligt svenskt barnhushåll slänger mat för tusenlappar per år och lägger
+1 -1
View File
@@ -14,7 +14,7 @@ tryck bort. Svenska först. Stora tryckytor (min 48 pt). Grön/varm palett (`src
5 steg, allt frivilligt, progressindikator: (1) primärt mål → (2) kosthållning + 5 steg, allt frivilligt, progressindikator: (1) primärt mål → (2) kosthållning +
allergier (med löftet "rätter med dina allergener visas aldrig") → (3) kroppsdata för allergier (med löftet "rätter med dina allergener visas aldrig") → (3) kroppsdata för
kalorimål, med icke-medicinsk-disclaimer → (4) hushåll: skapa/gå med via kod/hoppa över → kalorimål, med icke-medicinsk-disclaimer → (4) hushåll: skapa/gå med via kod/hoppa över →
(5) enkelt vs exakt läge (§5), kombinerbart. Registrering startar 7-dagars trial utan kort. (5) enkelt vs exakt läge (§5), kombinerbart. Registrering startar 14-dagars trial utan kort.
## Flikarna ## Flikarna
+1 -1
View File
@@ -9,7 +9,7 @@ Fel: `{ "error": { code, message, details?, correlationId } }`. Rate limit 300/m
| Metod | Path | Beskrivning | | Metod | Path | Beskrivning |
| ----- | ------------------------ | --------------------------------------------------------------- | | ----- | ------------------------ | --------------------------------------------------------------- |
| POST | /v1/auth/register | Skapa konto; startar 7-dagars trial; returnerar tokens | | POST | /v1/auth/register | Skapa konto; startar 14-dagars trial; returnerar tokens |
| POST | /v1/auth/login | Logga in | | POST | /v1/auth/login | Logga in |
| POST | /v1/auth/refresh | Rotera refresh-token (återanvändning → hela familjen revokeras) | | POST | /v1/auth/refresh | Rotera refresh-token (återanvändning → hela familjen revokeras) |
| POST | /v1/auth/logout | Revokera alla sessioner | | POST | /v1/auth/logout | Revokera alla sessioner |
+1 -1
View File
@@ -1,7 +1,7 @@
# Del 13 Subscriptions # Del 13 Subscriptions
Planer (spec §45): Household 79 kr (3 pers), Family 129 kr (6), Large Household 169 kr (12). Planer (spec §45): Household 79 kr (3 pers), Family 129 kr (6), Large Household 169 kr (12).
Fair use-kvoter för AI: 300/600/1000 skanningar/mån. Gratis: 10. Trial: 7 dagar full Fair use-kvoter för AI: 300/600/1000 skanningar/mån. Gratis: 10. Trial: 14 dagar full
tillgång (Family-nivå) utan kort, startar vid registrering (spec §46). tillgång (Family-nivå) utan kort, startar vid registrering (spec §46).
## Arkitekturprincip ## Arkitekturprincip
+2 -2
View File
@@ -27,7 +27,7 @@ utifrån det ni faktiskt har hemma, vad som bör användas snart och vad ni gill
• Full insyn: "Vad {NAMN} vet om mig" går att rätta, pausa och radera • Full insyn: "Vad {NAMN} vet om mig" går att rätta, pausa och radera
Gratis: 10 AI-skanningar/månad, manuellt lager, sparade recept och enkel loggning. Gratis: 10 AI-skanningar/månad, manuellt lager, sparade recept och enkel loggning.
Premium (7 dagar gratis, inget kort): obegränsat lager, veckoplan, delning och Premium (14 dagar gratis, inget kort): obegränsat lager, veckoplan, delning och
fler AI-skanningar. fler AI-skanningar.
**Nyckelord (100, App Store):** **Nyckelord (100, App Store):**
@@ -58,7 +58,7 @@ what you like.
• Full transparency: "What {NAME} knows about me" can be corrected, paused and deleted • Full transparency: "What {NAME} knows about me" can be corrected, paused and deleted
Free: 10 AI scans/month, manual inventory, saved recipes and simple logging. Free: 10 AI scans/month, manual inventory, saved recipes and simple logging.
Premium (7-day free trial, no card): unlimited inventory, week planning, sharing Premium (14-day free trial, no card): unlimited inventory, week planning, sharing
and more AI scans. and more AI scans.
**Keywords:** **Keywords:**
+1 -1
View File
@@ -110,7 +110,7 @@ personuppgiftsbiträdesavtal. Inga uppgifter säljs eller delas för marknadsfö
5. **Användarinnehåll**: recept du publicerar modereras. Du garanterar att du 5. **Användarinnehåll**: recept du publicerar modereras. Du garanterar att du
har rätt till innehåll du laddar upp; upphovsrättsintrång tas bort. har rätt till innehåll du laddar upp; upphovsrättsintrång tas bort.
6. **Prenumerationer**: köp och förnyelser hanteras av App Store/Google Play 6. **Prenumerationer**: köp och förnyelser hanteras av App Store/Google Play
enligt deras villkor; provperioden är 7 dagar utan kort. enligt deras villkor; provperioden är 14 dagar utan kort.
7. **Ansvarsbegränsning**: tjänsten tillhandahålls "i befintligt skick"; 7. **Ansvarsbegränsning**: tjänsten tillhandahålls "i befintligt skick";
ansvar begränsas till vad tvingande lag medger. ansvar begränsas till vad tvingande lag medger.
8. **Ändringar**: väsentliga villkorsändringar meddelas i appen minst 30 dagar 8. **Ändringar**: väsentliga villkorsändringar meddelas i appen minst 30 dagar
+1 -1
View File
@@ -61,7 +61,7 @@ export function computeEntitlements(
} }
} }
// 2. Trial: 7 dagar full tillgång utan kort (spec §46). Family-nivå under trial. // 2. Trial: 14 dagar full tillgång utan kort (spec §46). Family-nivå under trial.
if (trial && trial.endsAt > now) { if (trial && trial.endsAt > now) {
const def = PLAN_DEFINITIONS.family; const def = PLAN_DEFINITIONS.family;
return { return {
@@ -48,7 +48,7 @@ describe("entitlements (spec §4547)", () => {
); );
expect(ent.plan).toBe("free"); expect(ent.plan).toBe("free");
}); });
it("trial ger full tillgång i 7 dagar (spec §46)", () => { it("trial ger full tillgång i 14 dagar (spec §46)", () => {
const start = new Date("2026-08-01T00:00:00Z"); const start = new Date("2026-08-01T00:00:00Z");
const ent = computeEntitlements( const ent = computeEntitlements(
null, null,