From 1306fc08fd0eb5ce52b39e75658326942da59758 Mon Sep 17 00:00:00 2001 From: barckcode Date: Fri, 16 Oct 2026 16:26:25 +0200 Subject: [PATCH] Add token packs clause to the Terms of Service (EN + ES) One-time purchase of extra tokens for one model: 6-month validity from the last purchase of that model (extends the whole remaining balance), consumed only after the period allowance, usable only with an active inference membership (premium tier for premium models) and paused otherwise while the expiry keeps running, non-refundable with the EU withdrawal waiver on immediate supply, refunds/chargebacks remove the credited tokens, other limits still apply, prices include taxes. Page date moved to 2026-10-16. Co-Authored-By: Claude Opus 5.5 --- src/pages/es/terms.astro | 19 +++- src/pages/terms.astro | 18 +++- src/tests/legal/tokenPacksTerms.test.ts | 87 +++++++++++++++++++ .../legal/workspaceAcceptableUse.test.ts | 5 +- 4 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/tests/legal/tokenPacksTerms.test.ts diff --git a/src/pages/es/terms.astro b/src/pages/es/terms.astro index 02b71af6..e856ea9f 100644 --- a/src/pages/es/terms.astro +++ b/src/pages/es/terms.astro @@ -2,7 +2,7 @@ import Legal from '../../layouts/NanLegal.astro'; --- - +

NaN está operada por Helmcode S.L. (NIF B44788511), Avenida Quinto Centenario 27, Santiago del Teide, España. Contacto: info@helmcode.com. @@ -57,6 +57,23 @@ import Legal from '../../layouts/NanLegal.astro'; Las instantáneas borradas no se pueden recuperar.

+

+ Paquetes de tokens. Un paquete de tokens es una compra única de tokens extra para un solo modelo; + no es una suscripción y no se renueva. Los tokens comprados son válidos durante 6 meses desde tu última compra para + ese modelo: cada nueva compra para el mismo modelo suma sus tokens y amplía todo el saldo restante de ese modelo a + 6 meses desde esa compra. Los tokens caducados se pierden. Los tokens extra solo se usan cuando has agotado tu + cuota mensual o del periodo para ese modelo; la cuota se sigue renovando con normalidad y nunca consume ni + reinicia el saldo extra. Los tokens extra solo se pueden usar mientras tengas una membresía de inferencia activa + (y el tier premium para los modelos premium). Si tu membresía termina o pierdes el acceso a un modelo premium, el + saldo queda en pausa y la fecha de caducidad sigue corriendo. Los paquetes de tokens no son reembolsables. Según + la normativa de consumo de la UE, el contenido digital está sujeto normalmente a un derecho de desistimiento: los + paquetes de tokens se suministran de inmediato a petición expresa tuya, y aceptas que pierdes tu derecho de + desistimiento una vez suministrados. Un reembolso exigido por ley, o un contracargo o disputa del pago, retira + los tokens abonados por esa compra de tu saldo. Los paquetes de tokens no levantan ningún otro límite: siguen + aplicándose la concurrencia, límites de peticiones y uso razonable. Los precios se muestran antes de la compra e + incluyen impuestos; no se añade IVA en el pago. +

+

Uso aceptable de los workspaces

Este apartado se aplica desde el 6 de octubre de 2026. Los workspaces son máquinas personales para tu propio diff --git a/src/pages/terms.astro b/src/pages/terms.astro index e695dac4..a48bbe80 100644 --- a/src/pages/terms.astro +++ b/src/pages/terms.astro @@ -2,7 +2,7 @@ import Legal from '../layouts/NanLegal.astro'; --- - +

NaN is operated by Helmcode S.L. (NIF B44788511), Avenida Quinto Centenario 27, Santiago del Teide, Spain. Contact: info@helmcode.com. @@ -51,6 +51,22 @@ import Legal from '../layouts/NanLegal.astro'; older kept snapshots are deleted with the next daily backup. Deleted snapshots cannot be recovered.

+

+ Token packs. A token pack is a one-time purchase of extra tokens for a single model; it is not a + subscription and does not renew. Purchased tokens are valid for 6 months from your last purchase for that model: + each new purchase for the same model adds its tokens and extends the whole remaining balance of that model to 6 + months from that purchase. Expired tokens are lost. Extra tokens are only used once your monthly or period + allowance for that model is used up; the allowance keeps resetting as usual and never consumes or resets the extra + balance. Extra tokens are only usable while you have an active inference membership (and the premium tier for + premium models). If your membership ends or you lose access to a premium model, the balance is paused and the + expiry date keeps running. Token packs are non-refundable. Under EU consumer law, digital content is normally + subject to a right of withdrawal: token packs are supplied immediately at your express request, and you + acknowledge that you lose your right of withdrawal once they are supplied. A refund required by law, or a + chargeback or payment dispute, removes the tokens credited by that purchase from your balance. Token packs do not + lift any other limit: concurrency, rate limits and fair use still apply. Prices are shown before purchase and + include taxes; no VAT is added at checkout. +

+

Workspace acceptable use

This section applies from October 6, 2026. Workspaces are personal machines for your own development work. You diff --git a/src/tests/legal/tokenPacksTerms.test.ts b/src/tests/legal/tokenPacksTerms.test.ts new file mode 100644 index 00000000..14e0c5dd --- /dev/null +++ b/src/tests/legal/tokenPacksTerms.test.ts @@ -0,0 +1,87 @@ +import { describe, expect, test } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, resolve } from 'node:path'; + +/** + * Token packs (one-time purchase of extra tokens for one model): the terms are + * the contract the portal copy points at. These tests pin the commitments that + * must never drift: one model per pack, 6-month validity from the last purchase + * of that model (extending the whole remaining balance), consumed only after + * the period allowance, usable only with an active inference membership (and + * premium for premium models), paused otherwise while expiry keeps running, no + * refunds, EU withdrawal waiver on immediate supply, refunds/chargebacks remove + * the credited tokens, other limits still apply, prices with taxes included. + */ +const here = dirname(fileURLToPath(import.meta.url)); +const pages = resolve(here, '../../pages'); +const flat = (p: string) => readFileSync(resolve(pages, p), 'utf-8').replace(/\s+/g, ' '); + +function section(src: string): string { + const m = src.match(/

(.*?)<\/p>/); + expect(m, 'token-packs paragraph present').toBeTruthy(); + return m![1].replace(/<[^>]+>/g, ''); +} + +function sitsUnder(src: string, heading: string) { + const h = src.indexOf(`

${heading}

`); + const next = src.indexOf(' { + const src = flat('terms.astro'); + const p = section(src); + + test('sits under "Membership and payments"', () => sitsUnder(src, 'Membership and payments')); + + test('states every commitment', () => { + expect(p).toContain('one-time purchase of extra tokens for a single model'); + expect(p).toContain('valid for 6 months from your last purchase for that model'); + expect(p).toContain('extends the whole remaining balance of that model'); + expect(p).toContain('only used once your monthly or period allowance for that model is used up'); + expect(p).toContain('the allowance keeps resetting as usual'); + expect(p).toContain('only usable while you have an active inference membership'); + expect(p).toContain('premium tier for premium models'); + expect(p).toContain('paused and the expiry date keeps running'); + expect(p).toContain('Token packs are non-refundable'); + expect(p).toContain('supplied immediately at your express request'); + expect(p).toContain('you lose your right of withdrawal once they are supplied'); + expect(p).toContain('removes the tokens credited by that purchase'); + expect(p).toContain('concurrency, rate limits and fair use'); + expect(p).toContain('Prices are shown before purchase and include taxes; no VAT is added'); + }); +}); + +describe('terms: token packs (ES)', () => { + const src = flat('es/terms.astro'); + const p = section(src); + + test('sits under "Membresía y pagos"', () => sitsUnder(src, 'Membresía y pagos')); + + test('states every commitment', () => { + expect(p).toContain('compra única de tokens extra para un solo modelo'); + expect(p).toContain('válidos durante 6 meses desde tu última compra para ese modelo'); + expect(p).toContain('amplía todo el saldo restante de ese modelo'); + expect(p).toContain('solo se usan cuando has agotado tu cuota mensual o del periodo para ese modelo'); + expect(p).toContain('la cuota se sigue renovando con normalidad'); + expect(p).toContain('solo se pueden usar mientras tengas una membresía de inferencia activa'); + expect(p).toContain('tier premium para los modelos premium'); + expect(p).toContain('queda en pausa y la fecha de caducidad sigue corriendo'); + expect(p).toContain('Los paquetes de tokens no son reembolsables'); + expect(p).toContain('se suministran de inmediato a petición expresa tuya'); + expect(p).toContain('pierdes tu derecho de desistimiento una vez suministrados'); + expect(p).toContain('retira los tokens abonados por esa compra'); + expect(p).toContain('concurrencia, límites de peticiones y uso razonable'); + expect(p).toContain('Los precios se muestran antes de la compra e incluyen impuestos; no se añade IVA'); + }); +}); + +describe('terms: last updated', () => { + test.each(['terms.astro', 'es/terms.astro'])('%s', (f) => { + expect(flat(f)).toContain('updated="October 16, 2026"'); + }); +}); diff --git a/src/tests/legal/workspaceAcceptableUse.test.ts b/src/tests/legal/workspaceAcceptableUse.test.ts index 97478061..caf76512 100644 --- a/src/tests/legal/workspaceAcceptableUse.test.ts +++ b/src/tests/legal/workspaceAcceptableUse.test.ts @@ -79,8 +79,9 @@ describe.each(Object.entries(cases))('terms: workspace acceptable use (%s)', (_l test('marks the date it applies from, and the page date moved with it', () => { expect(s).toContain(c.since); - // Moved again on 2026-10-14 (open signup rewrote the community section). - expect(src).toContain('updated="October 14, 2026"'); + // Moved again on 2026-10-14 (open signup rewrote the community section) + // and on 2026-10-16 (token packs clause). + expect(src).toContain('updated="October 16, 2026"'); }); test.each(c.prohibited)('prohibits: %s', (item) => {