Skip to main content
    Compliance

    Legal acceptance methodology

    How Keypra OÜ records and preserves evidence that a user has accepted the current Terms of Service, Privacy Policy and related legal documents — and what we can produce on demand for a court, a Data Protection Authority or the user themselves.

    Last updated: May 2026

    1. Legal basis

    Acceptance of Terms of Service is the formation of a contract under Article 6(1)(b) GDPR (necessary for the performance of a contract). Acceptance of the Privacy Policy is an acknowledgement of the controller's Article 13 information notice. Neither is a withdrawable Article 6(1)(a) consent — they are evidence of contract formation and notice. Optional telemetry and marketing flags are stored separately in the consent ledger.

    2. What we capture at the moment of acceptance

    • User ID — the immutable Supabase auth UUID.
    • Document type & version — e.g. terms_of_service / 2026-05-09.
    • Content SHA-256 — cryptographic hash binding the receipt to the exact published text.
    • Timestamp — UTC, server-clock, set by Postgres on insert.
    • Surface — where the click happened (signup_email, signup_oauth_gate, re_consent, enterprise_invite_accept).
    • Verbatim checkbox label — the exact text the user saw next to the tickbox.
    • Locale — browser language.
    • IP address — captured from x-forwarded-for server-side, plus a salted SHA-256 hash so identification can be re-derived after the raw IP is purged.
    • Country code — derived from request headers.
    • User agent — full User-Agent string.
    • Receipt ID — the row's UUID.

    3. Tamper resistance

    • The legal_acceptances table is append-only. Database triggers reject every UPDATE and DELETE, including by service-role.
    • The legal_document_versions table is the single source of truth for the published text. Each row stores the immutable snapshot and its SHA-256 hash; the receipt references both via foreign key.
    • Row-Level Security: the data subject can read only their own receipts. Keypra staff with the admin role can read all receipts for legal-request fulfilment; nobody can write directly.
    • Inserts go exclusively through a server-side acceptance endpoint, which validates the session token, captures request headers, and writes one row per accepted document.

    4. Retention

    Receipts are kept for the lifetime of the contract plus the limitation period applicable in Estonia (Article 146 of the Estonian Law of Obligations Act — 3 years for general claims, 10 years for written agreements). Raw IP addresses are blanked 13 months after acceptance via a pg_cron job; the salted IP hash and all other fields remain, preserving the evidentiary chain while honouring data minimisation under Article 5(1)(c) GDPR.

    5. Re-consent on policy change

    When we publish a new version of the Terms or Privacy Policy, the LegalGatemiddleware redirects every signed-in user to /welcome/accept-terms on next navigation. The legal_acceptance_status RPC compares the user's most recent receipt against the latest published version per document and reportsneeds_acceptance: true when a new acceptance is required.

    6. Producing evidence on demand

    For each user/document, Keypra OÜ can produce a single PDF evidence pack containing every field listed in §2, alongside the archived snapshot of the accepted text. Users can download their own pack at any time fromSettings → Privacy → Legal acceptance history. A court order, DPA request or GDPR Article 15 subject access request can be served onlegal@keypra.com.

    7. Standards we align with

    • GDPR Article 7(1) — burden of proof of consent on the controller.
    • EDPB Guidelines 05/2020 on consent — recording and demonstrability.
    • eIDAS Regulation (EU) 910/2014 — admissibility of electronic records as evidence.
    • Estonian Personal Data Protection Act (IKS) — local enforcement standard.

    8. Withdrawal waiver (consumers, EU)

    EU consumers have a 14-day right of withdrawal from digital-service purchases under Directive 2011/83/EU and its Polish implementation. Article 16(m) allows that right to be waived only where the consumer has given express prior consent to immediate performance and acknowledged the loss of the withdrawal right. Keypra collects this consent as a separate, explicit checkbox at every paid checkout entry point — never bundled with acceptance of the Terms or Privacy Policy.

    • Surfaces. Shown at checkout_subscription, checkout_topup, checkout_capacity_boost and checkout_lecturer_license. Stripe Checkout is not opened until the consent row has been written.
    • Audience filter. Skipped for business buyers (entity_type === 'company') — the statutory right applies only to natural persons acting outside their trade or profession — and for users in regions blocked from self-service paid checkout.
    • Evidence row. Recorded in legal_acceptances with document_type='withdrawal_waiver', version label v2026-05, the verbatim waiver text, and whitelisted metadata (product key, buying_as, and the Stripe session ID when available).
    • Failure mode. If the consent row cannot be written, Stripe Checkout is not opened. There is no silent-fail path that activates a paid Service without a recorded waiver.
    • Confirmation. The purchase confirmation email re-states the waiver text and the right being waived, satisfying Article 8(7) of the Directive.
    • Contestability. Consumers may dispute the waiver or request a refund at billing@keypra.com. Statutory consumer rights under the country of residence remain unaffected.
    Keypra OÜ · Reg. 17502390 · Sepapaja tn 6, 15551 Tallinn, Estonia