diff --git a/src/pages/es/terms.astro b/src/pages/es/terms.astro index f1bf1be..d3a5454 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. @@ -28,6 +28,31 @@ import Legal from '../../layouts/NanLegal.astro'; La membresía es una suscripción mensual con impuestos incluidos, mes a mes, sin compromiso. Puedes cancelar cuando quieras; el acceso se mantiene hasta el final del periodo pagado.

+

+ Copias de seguridad de workspaces. Los workspaces no tienen copias de seguridad salvo + que el complemento de backups esté activo. Con el complemento, se toma una instantánea del disco del + workspace una vez al día y se conserva durante 7 días. Las instantáneas son consistentes ante caídas + (crash-consistent): restaurar una equivale a que la máquina se quede sin corriente en el momento en que se + tomó, así que los datos que el workspace aún no había escrito en disco no se incluyen y las bases de datos en + ejecución se recuperan como tras un corte de luz. Restaurar una instantánea recupera todo lo que había en el + disco en ese momento, incluido cualquier acceso que hayas configurado tú (por ejemplo claves SSH o ajustes del + servidor SSH que añadieras); la plataforma solo vuelve a aplicar tu clave SSH actual de NaN. Puedes restaurar + hasta 3 veces por workspace en cualquier periodo de 24 horas; no hay copias bajo demanda. Las instantáneas + solo se pueden restaurar mientras el complemento esté activo: durante un periodo de gracia tienes que asociar + el workspace a un slot activo (o renovar la membresía, si es un workspace gratuito) y volver a activar el + complemento, que se cobra de nuevo. Activar el complemento cobra el primer pago en el momento (prorrateado + hasta la fecha de renovación cuando se añade a la suscripción de un slot); desactivarlo lo elimina de + inmediato sin reembolso del mes en curso. Desactivar el complemento o eliminar el workspace borra todas sus + instantáneas de forma permanente. Si el slot del workspace termina, o un workspace gratuito pierde el + beneficio de la membresía, el complemento deja de cobrarse. Cuando termina la facturación, no se toman nuevas + instantáneas y las existentes se conservan hasta que se elimine el workspace al final de su periodo de + gracia. Si el workspace vuelve a estar al día pero el complemento no se reactiva en un plazo de 14 días, el + complemento termina y sus instantáneas se borran. Las instantáneas conservadas no se eliminan mientras + el complemento esté desactivado. Cuando el complemento se vuelve a activar, solo se pueden restaurar las + instantáneas de los últimos 7 días; las instantáneas conservadas más antiguas se eliminan con la siguiente + copia diaria. + Las instantáneas borradas no se pueden recuperar. +

Propiedad intelectual

diff --git a/src/pages/terms.astro b/src/pages/terms.astro index 6fb7148..5a5d592 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. @@ -28,6 +28,26 @@ import Legal from '../layouts/NanLegal.astro'; Membership is a monthly subscription with taxes included, month to month, with no commitment. You can cancel anytime; access runs until the end of the paid period.

+

+ Workspace backups. Workspaces have no backups unless the workspace backup add-on is + active. With the add-on, a snapshot of the workspace disk is taken once a day and kept for 7 days. + Snapshots are crash-consistent: restoring one is equivalent to the machine losing power at the moment the + snapshot was taken, so data the workspace had not yet written to disk is not included and running databases + recover as after a power cut. Restoring a snapshot brings back everything that was on the disk at that time, + including any access you configured yourself (for example SSH keys or SSH server settings you added); only + your current NaN SSH key is re-applied by the platform. You can restore up to 3 times per workspace in any + 24 hours; there are no on-demand backups. Snapshots can only be restored while the add-on is active: during a + grace period you must attach the workspace to an active slot (or renew the membership, for a free workspace) + and turn the add-on on again, which is billed again. Enabling the add-on charges the first payment right away + (prorated to the renewal date when it is added to a slot subscription); turning it off removes it immediately + with no refund for the current month. Turning the add-on off or deleting the workspace deletes all its + snapshots permanently. If the workspace's slot ends, or a free workspace loses the membership benefit, the + add-on stops being billed. When billing ends, no new snapshots are taken and existing snapshots are kept until + the workspace is deleted at the end of its grace period. If the workspace is back in good standing but the + add-on is not turned on again within 14 days, the add-on ends and its snapshots are deleted. Kept snapshots are not pruned while + the add-on is off. After the add-on is turned on again, only snapshots from the last 7 days can be restored; + older kept snapshots are deleted with the next daily backup. Deleted snapshots cannot be recovered. +

Intellectual property

diff --git a/src/tests/legal/workspaceBackupTerms.test.ts b/src/tests/legal/workspaceBackupTerms.test.ts new file mode 100644 index 0000000..e29d09c --- /dev/null +++ b/src/tests/legal/workspaceBackupTerms.test.ts @@ -0,0 +1,110 @@ +import { describe, expect, test } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, resolve } from 'node:path'; + +/** + * Workspace backup add-on (helmcode/nan#130): the terms are the contract the + * UI copy points at. These tests pin the promises that must never drift: + * no backups without the add-on, daily crash-consistent snapshots, 7-day + * retention, deletion on disable/workspace deletion, snapshots kept until the + * workspace is deleted when a slot or benefit ends, and no partial refund. + */ +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, 'workspace-backups paragraph present').toBeTruthy(); + return m![1].replace(/<[^>]+>/g, ''); +} + +describe('terms: workspace backups (EN)', () => { + const src = flat('terms.astro'); + const p = section(src); + + test('sits under "Membership and payments"', () => { + const h = src.indexOf('

Membership and payments

'); + const next = src.indexOf('

', h + 1); + const at = src.indexOf('id="workspace-backups"'); + expect(h).toBeGreaterThan(-1); + expect(at).toBeGreaterThan(h); + expect(at).toBeLessThan(next); + }); + + test('states every promise', () => { + expect(p).toContain('no backups unless the workspace backup add-on is active'); + expect(p).toContain('once a day and kept for 7 days'); + expect(p).toContain('crash-consistent'); + expect(p).toContain('power'); + expect(p).toContain('no refund for the current month'); + expect(p).toContain('Turning the add-on off or deleting the workspace deletes all its snapshots permanently'); + expect(p).toContain('the add-on stops being billed'); + expect(p).toContain('including any access you configured yourself'); + expect(p).toContain('only your current NaN SSH key is re-applied'); + }); + + test('restore limits and grace rules (product decision 2026-10-02)', () => { + expect(p).toContain('You can restore up to 3 times per workspace in any 24 hours'); + expect(p).toContain('there are no on-demand backups'); + expect(p).toContain('Snapshots can only be restored while the add-on is active'); + expect(p).toContain('attach the workspace to an active slot (or renew the membership, for a free workspace) and turn the add-on on again, which is billed again'); + expect(p).toContain('When billing ends, no new snapshots are taken and existing snapshots are kept until the workspace is deleted'); + expect(p).toContain('within 14 days'); + }); + + test('after turning the add-on on again only the last 7 days are restorable (cloud-api #295)', () => { + expect(p).toContain('Kept snapshots are not pruned while the add-on is off.'); + expect(p).toContain('After the add-on is turned on again, only snapshots from the last 7 days can be restored; older kept snapshots are deleted with the next daily backup.'); + // Never promises that an older kept snapshot can be restored. + expect(p).not.toContain('restore the one you need first'); + }); + + test('never promises deletion at slot end (owner rule 2026-10-02)', () => { + const clause = p.slice(p.indexOf('When billing ends')).split('.')[0]; + expect(clause).toContain('no new snapshots are taken'); + expect(clause).toContain('existing snapshots are kept until the workspace is deleted'); + expect(clause).not.toMatch(/snapshots are deleted|deletes all/); + }); +}); + +describe('terms: workspace backups (ES)', () => { + const src = flat('es/terms.astro'); + const p = section(src); + + test('sits under "Membresía y pagos"', () => { + const h = src.indexOf('

Membresía y pagos

'); + const next = src.indexOf('

', h + 1); + const at = src.indexOf('id="workspace-backups"'); + expect(h).toBeGreaterThan(-1); + expect(at).toBeGreaterThan(h); + expect(at).toBeLessThan(next); + }); + + test('states every promise', () => { + expect(p).toContain('no tienen copias de seguridad salvo que el complemento de backups esté activo'); + expect(p).toContain('una vez al día y se conserva durante 7 días'); + expect(p).toContain('crash-consistent'); + expect(p).toContain('sin reembolso del mes en curso'); + expect(p).toContain('Desactivar el complemento o eliminar el workspace borra todas sus instantáneas de forma permanente'); + expect(p).toContain('el complemento deja de cobrarse'); + expect(p).toContain('incluido cualquier acceso que hayas configurado tú'); + expect(p).toContain('solo vuelve a aplicar tu clave SSH actual de NaN'); + }); + + test('límites de restauración y reglas de gracia', () => { + expect(p).toContain('Puedes restaurar hasta 3 veces por workspace en cualquier periodo de 24 horas'); + expect(p).toContain('no hay copias bajo demanda'); + expect(p).toContain('Las instantáneas solo se pueden restaurar mientras el complemento esté activo'); + expect(p).toContain('volver a activar el complemento, que se cobra de nuevo'); + expect(p).toContain('Cuando termina la facturación, no se toman nuevas instantáneas y las existentes se conservan hasta que se elimine el workspace'); + expect(p).toContain('en un plazo de 14 días'); + }); + + test('al reactivar el complemento solo se restauran los últimos 7 días', () => { + expect(p).toContain('Las instantáneas conservadas no se eliminan mientras el complemento esté desactivado.'); + expect(p).toContain('Cuando el complemento se vuelve a activar, solo se pueden restaurar las instantáneas de los últimos 7 días; las instantáneas conservadas más antiguas se eliminan con la siguiente copia diaria.'); + expect(p).not.toContain('restaura antes la que necesites'); + }); +});